ForkSync keeps a fork current with upstream while preserving a small layer of custom commits.
The intended user flow is:
- Fork a repo on GitHub.
- Clone your fork locally.
- Run
forksync init. - Keep working on your output branch, which defaults to
main. - Let ForkSync replay your fork changes onto new upstream updates automatically.
Public install target:
pnpx @tabslabs/forksync initCurrent repo-local dogfood flow:
cargo run --bin forksync -- initforksync init will:
- detect the upstream remote when possible
- generate
.forksync.yml - generate
.github/workflows/forksync.yml - create/update
forksync/liveandforksync/patches - try to publish the managed refs for you
- offer a minimal interactive setup for:
- direct publication to the output branch when it looks safe
OpenCodeorNo AI- optional public registry opt-in for GitHub-hosted forks
After that, keep working on your output branch and let the generated GitHub Action run ForkSync.
ForkSync tracks three primary branches:
mainor your configured output branch: your normal authoring branchforksync/live: the generated synced resultforksync/patches: an internal snapshot/debug branch
At sync time, ForkSync:
- Fetches upstream and origin.
- Builds a fresh candidate branch from the latest upstream
HEAD. - Rewrites ForkSync-managed files from the current config.
- Replays imported public source commits, if configured.
- Replays your local authored commits last.
- Uses the agent only when replay conflicts require repair.
- Publishes
forksync/liveand, by default, force-updates the output branch with explicit--force-with-leaseprotection.
The design rule is simple:
- upstream is the base truth
- your fork changes are a patch layer
- imported public sources are replayed before your local commits
- ForkSync automatically resolves what it can first, then uses the agent for conflicts that still need repair
ForkSync now has a public-source model for sharing reusable fork layers.
- A source is a Git repo plus tracked branch.
- Configured sources live in
sources[]in.forksync.yml. forksync syncfetches each enabled source, derives its patch layer from the merge-base with upstream, and replays those commits before your own local commits.- Source ordering is deterministic and internal. It is not a user-facing knob.
You can configure sources during init:
forksync init --source owner/repo#mainOr later:
forksync registry add owner/repo#main
forksync registry list
forksync registry remove owner/repo#mainThe repository also contains a Cloudflare Worker + D1 scaffold under registry/ for a public browse/search/select experience.
Current registry URLs:
- production:
https://forksync-registry-prod.prosammer.workers.dev - staging:
https://forksync-registry-staging.prosammer.workers.dev
Generated workflows use:
uses: monadoid/forksync@v1The action is a JavaScript launcher that prefers prebuilt release binaries and only falls back to source builds as a dev escape hatch.
Important runtime behavior:
- OpenCode install is automatic only when OpenCode is selected.
- normal CLI output is intentionally quiet
- leased pushes are the correctness guard for remote ref publication
- GitHub workflow
concurrencyremains the scheduler guard for hosted runs
Important defaults:
- output branch: detected default branch, usually
main - live branch:
forksync/live - patch/debug branch:
forksync/patches - default action ref:
monadoid/forksync@v1 - validation mode:
noneunless you provide commands - public agent choices:
OpenCodeandNo AI - default OpenCode model:
opencode/gpt-5-nano
Validation commands can already be set during init:
forksync init --build-command "cargo build --workspace" --test-command "cargo test --workspace"Safe local demo commands:
forksync dev init --prepare-only
forksync dev init
forksync dev actUse forksync dev act to smoke-test the real action path locally.
ForkSync uses structured tracing internally.
Use:
--verbosefor human-readable logs--json-logsfor structured logsOTEL_EXPORTER_OTLP_ENDPOINT=...to export telemetry
- Publish the first real versioned GitHub Action release and move
@v1onto an immutable semver release flow. - Publish the npm package and other non-Rust-first install paths for public users.
- Finish the bootstrap protected-branch fallback by auto-opening the PR, not just publishing the fallback branch.
- Finish standing conflict PR reuse end to end on GitHub-hosted runs.
- Expand GitHub-side auth and infra failure coverage.
- Add an interactive validation wizard instead of only flag-based validation setup.
- Finish public registry publish/update/unpublish from the Rust CLI against the deployed Worker with stronger end-to-end coverage.
- Add a custom registry domain and document its long-term operating model.
- Add example configs, troubleshooting docs, and end-user release/update guidance.
- Decide the long-term fallback plan if OpenCode runtime or free-model assumptions change materially.
- Decide whether future public sharing should stay registry-style or evolve toward richer patch stacking.
- Add conflict-memory and stronger automatic repair behavior.
Contributor rules for this repository:
- always follow TDD
- always write strongly typed schemas and think schema-first
- use explicit state machines where they clarify lifecycle transitions or side-effect boundaries
- keep the CLI and workflow wrappers thin over reusable library APIs
- add or update tests whenever behavior changes
- prefer deterministic engine behavior over implicit magic
- preserve the swappable agent abstraction even while OpenCode is the only fully wired public provider
- update this README when the product shape or TODO list changes
Definition of done for a feature:
- A failing test exists for the intended behavior.
- Minimal implementation makes the test pass.
- Refactor preserves passing tests.
- Docs are updated if user-facing behavior changed.