Spec-first
Plan locally, project outward
Start in openspec/changes/, define proposal and tasks, then sync to the tracker when the plan is ready.
OpenSpec × GitHub Issues
Plan in OpenSpec, sync to issues and boards, and ship from one source of truth. Start spec-first or pull an existing board issue and plan implementation tasks locally.
Dogfooded here: every shipped change traces from OpenSpec plan to issue to release notes.
How it works
specsync supports both entry points: spec-first and issue-first (from your issue tracker). Start from either side, keep OpenSpec as the source of truth, and synchronize issue tracker issues/boards as work evolves.
Spec-first
Start in openspec/changes/, define proposal and tasks, then sync to the tracker when the plan is ready.
Issue-first
Start from an existing issue tracker issue via specsync pull, refine locally, and keep issue plus board state aligned.
Features
specsync is a small CLI binary: no daemon, no SDK lock-in, and no mandatory central config file. In GitHub mode it uses gh, with flags and env vars controlling behavior.
Start from local proposal.md/tasks.md or pull an existing issue tracker issue with specsync pull.
specsync init (or pull -init) makes a scratch openspec/ that git never sees, so an agent can pull an issue and sync in any repo. Nothing is created unless you ask; a user-level default store is also supported.
A design.md renders as ## Design notes in the synced issue, so decisions made while planning aren't lost if the local worktree is force-removed. Oversized notes overflow to a linked issue comment instead of getting truncated.
specsync scan shows what already exists for an area — in-flight changes, loose issues, recent commits — before you plan.
specsync status shows where your work stands: pull request, checks, review, unpushed and uncommitted work, how far the base has moved and whether a merge would conflict — with the commands to catch up. Under an epic or with blockers it also lists every related item across your repos, and how to pick each piece up again, including its agent session through an optional provider. Read-only, and -json gives agents the same facts.
specsync overview lists every change, worktree and open request in the clones under your workspace, grouped by epic, then work under no epic, then branches with no change. Scope it with -repo, -epic, -mine, -attention, -stage or -unattached. Read-only; -json for agents.
specsync spinoff spawns a new linked change from a discovery, keeping the parent scoped and marking the source task as moved.
specsync idea "Thought" files a vague or elaborate idea as a GitHub issue in your ideas inbox; specsync ideas lists open intake. Graduate with specsync pull -issue <n>.
Declare gates and steps in openspec/specsync.yml; specsync next reads the work's state and prints the next step and its command, specsync flow marks where you are. Commands from the repo run only after specsync trust.
Declare reviewable slices in tasks.md, each with a contract, an order and a size budget. specsync slices shows each slice's branch and pull request, slice start opens the next one stacked on the last, and sync -slices mirrors them as child issues.
Run specsync -change my-change as often as needed. specsync finds the change's issue from its identity marker, the ref cache or the branch name (feat/42-my-change) and updates it instead of creating a duplicate; pull without -issue resolves the same way.
specsync adopt -issue 3691 -change my-change binds a change and an issue that already exist independently, writing the ref cache before touching the issue body so the link holds immediately instead of racing search indexing.
Set stage explicitly with specsync set-stage my-change [active|blocked|in-review|complete] so progress is visible and committed in metadata.
Inside a change's worktree, set-stage, note and archive find the change from the branch — feat/42-my-change or an Orca workspace's user/my-change. On main nothing resolves, so an agent there can't act on a change by accident.
With worktrees.launcher: orca, specsync start my-change creates the change's worktree through Orca, linked to its issue, so Orca's agent gets the spec as its brief; the branch stays unpublished until you push. workspace setup and workspace archive in orca.yaml hooks keep the stage in step: active when a workspace starts, back to derived when it is archived.
Set priorities (1-100) with specsync set-priority my-change 85. Agents respect priority when deciding what to work on next — humans direct focus.
Project and sync with specsync -change my-change -project my-org/6. Add -status-map "active=In Progress,complete=Done" to align board columns with change stages.
specsync epic "Feature X" --repo org/planning --child org/backend#12 --child frontend-slug mints a coordination issue and wires every child — local change or existing issue, any repo — to it, idempotently.
specsync agent-help provides command guidance without manuals. Use --json for machine-readable schema suitable for agents and automation.
specsync doctor detects canonical and legacy AI agent skill installations (Claude Code, Agent Skills, legacy paths), validates CLAUDE.md imports, checks that the openspec CLI is installed, and recommends fixes.
-provider mcp projects changes through any external MCP server instead of gh — Linear, Jira, GitHub, or in-house. Speaks the current MCP spec with automatic fallback to legacy handshake-based servers.
A synced issue shows title and task checklist first — Proposal, Original ask, and Discoveries render inside collapsed <details> blocks, one click away, nothing removed.
specsync verify -refs finds commit hashes and issue or PR references in change documents that no longer resolve after a rebase. Read-only and advisory; it never guesses a replacement.
new, start, save, gates, update and pr prep/open do the mechanical parts of starting, checking and opening work, each with a dry run. They refuse secrets, forbidden trailers, unsafe pushes and unconfirmed PRs; the conventions come from openspec/specsync.yml.
specsync status and verify -size flag a branch that is over a files, lines or commits budget, or that mixes commit scopes, before review starts. Advisory by default; -fail-on-oversized makes it a gate.
specsync review-map turns a branch into a checklist: the paths the author declared as needing judgement first, then each commit with its files and sizes, then totals by category. -equivalent proves a rewritten branch holds the same content.
specsync lint checks titles, headers, sentences and length against a short standard, advisory unless -fail. pr-body -template writes a brief PR body from the change and your repo's template. Never rewrites your text.
specsync release-plan highlights shipped changes, loose/unlinked work, archive candidates, and advisory release impact from spec-level deltas.
specsync changelog writes a Keep a Changelog section from your shipped changes — one entry per change, release notes authored at planning time, never a raw commit dump.
specsync audit cross-references archived changes against GitHub PRs to find archived-but-unmerged work. Add -mark-shipped to record the final lifecycle step.
specsync cleanup lists worktrees whose work is provably merged and, with -apply, removes them and their branches. It never touches dirty trees, ignored files, protected or shared branches, unpushed commits, open requests or live sessions, and re-checks each one just before removal; hooks run only after specsync trust.
In practice
Project a local plan outward, or pull an existing issue inward — either way you end up in the same loop.
Repository Evidence
Not a staged demo — follow one real change, the v0.8.0 board projection, through every form it takes:
Changelog
specsync archive -reason not-planned|duplicate closes an abandoned or duplicate change with the matching reason, without -force. #209specsync changes -issues shows each change's issue and state and flags changes whose issue was closed or whose tasks are all checked while the issue is open. #208set-stage, note, archive) now find it from the branch you are on, including Orca's <user>/<workspace> branches. #200specsync workspace setup and workspace archive keep a change in step with an Orca workspace, turning a workspace started from an issue into a change. #202tasks.md, each with a contract, an order and a size budget, and see each slice's branch, worktree and pull request with specsync slices. #194specsync status and specsync verify -size now flag a branch that is too large or that mixes unrelated concerns, before review starts. #193specsync review-map turns a branch into a review checklist: what to read first, what is mechanical, and which commit introduced what, plus a check that a rewritten branch holds the same content. #195specsync start can create the change's worktree as an Orca workspace, linked to its issue (worktrees.launcher: orca). #228specsync status: the state of your current work, with PR, checks, review and local state. #186specsync status can now show how to resume each piece of work: the worktree to open, the last note on the change, and, through an optional external provider, the agent session that was working there. #188specsync verify -refs finds commit hashes and request references in your change documents that no longer resolve, for example after a rebase. #196specsync next and a flow section in openspec/specsync.yml: define your gates and steps once, and see the next step for the work in front of you. #189specsync overview for all work across repos, and show every related item in specsync status. #187specsync cleanup: list and remove finished worktrees and branches safely, and report the archive follow-up for their changes. #190specsync agent-help now guides agents toward one branch and worktree per issue, and documents pull's existing -worktree/-worktree-dir flags. #162sync -project (and openspec/specsync.yml's board target) now actually projects issues onto the configured GitHub Projects board — it previously reported BoardConfigured: true and silently did nothing. pull was unaffected; this restores parity for sync. #159specsync and stage:<stage> labels are no longer added by default — issue identity was never based on them (the body marker is), and stage duplicates the Projects board Status column wherever a board is used. Pass -labels to sync to restore the previous always-on behavior. A sync without the flag also removes these labels from issues that already carry them from before this change. #157