OpenSpec × GitHub Issues

The issue is the spec.

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.

npm npm install -g @androidand/specsync
go go install github.com/androidand/specsync/cmd/specsync@latest

Dogfooded here: every shipped change traces from OpenSpec plan to issue to release notes.

How it works

Two flows. One source of truth.

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

Plan locally, project outward

Start in openspec/changes/, define proposal and tasks, then sync to the tracker when the plan is ready.

Issue-first

Pull inward, then evolve in spec

Start from an existing issue tracker issue via specsync pull, refine locally, and keep issue plus board state aligned.

Everything a spec workflow needs. Nothing heavyweight.

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.

Plan

Spec-first or issue-first

Start from local proposal.md/tasks.md or pull an existing issue tracker issue with specsync pull.

Works in repos with no openspec/

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.

Design notes survive the worktree

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.

Planning scan

specsync scan shows what already exists for an area — in-flight changes, loose issues, recent commits — before you plan.

Where your work stands

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.

All your work, across repos

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.

Spin off emergent work

specsync spinoff spawns a new linked change from a discovery, keeping the parent scoped and marking the source task as moved.

Capture ideas

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>.

Define your flow once, get the next step

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.

Plan a big change as slices

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.

Collaborate

Idempotent

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.

Adopt an existing issue

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.

Workflow state management

Set stage explicitly with specsync set-stage my-change [active|blocked|in-review|complete] so progress is visible and committed in metadata.

The branch names the change

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.

Orca workspaces

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.

Priority-driven dispatch

Set priorities (1-100) with specsync set-priority my-change 85. Agents respect priority when deciding what to work on next — humans direct focus.

Projects board sync

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.

Cross-repo epic scaffolding

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.

CLI self-documentation

specsync agent-help provides command guidance without manuals. Use --json for machine-readable schema suitable for agents and automation.

Agent skill diagnostics

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.

Any MCP-connected tracker

-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 clean issue, not a wall of text

A synced issue shows title and task checklist first — Proposal, Original ask, and Discoveries render inside collapsed <details> blocks, one click away, nothing removed.

Catch stale references in your docs

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.

The same steps every time

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.

Review

Warns before a pull request is too big

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.

A map for reviewing a big pull request

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.

Short, consistent issues and PRs

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.

Ship

Release follow-up

specsync release-plan highlights shipped changes, loose/unlinked work, archive candidates, and advisory release impact from spec-level deltas.

Spec-driven changelog

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.

Archive audit

specsync audit cross-references archived changes against GitHub PRs to find archived-but-unmerged work. Add -mark-shipped to record the final lifecycle step.

Clean up finished work safely

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

Two commands, both directions.

Project a local plan outward, or pull an existing issue inward — either way you end up in the same loop.


Repository Evidence

specsync is dogfooded on specsync itself.

Not a staged demo — follow one real change, the v0.8.0 board projection, through every form it takes:

1 · Planning artifact openspec/changes/github-projects-compatibility/ Proposal and task checklist, written before any code. Pinned at the v0.8.0 tag so the link never rots. 2 · Tracker projection specsync#37 The issue specsync generated from that change — same body, live task checklist, closed when the work shipped. 3 · Shipped output v0.8.0 release notes The changelog entry derived from the same change, linking back to #37. The loop closes itself.


Changelog

Recent releases

v0.15.0 Nov 11, 2026
Changed
  • specsync archive -reason not-planned|duplicate closes an abandoned or duplicate change with the matching reason, without -force. #209
  • specsync 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. #208
  • Commands that act on one change (set-stage, note, archive) now find it from the branch you are on, including Orca's <user>/<workspace> branches. #200
  • specsync workspace setup and workspace archive keep a change in step with an Orca workspace, turning a workspace started from an issue into a change. #202
  • Plan a large change as slices in tasks.md, each with a contract, an order and a size budget, and see each slice's branch, worktree and pull request with specsync slices. #194
  • specsync status and specsync verify -size now flag a branch that is too large or that mixes unrelated concerns, before review starts. #193
  • specsync 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. #195
  • Smooth first use of specsync in a repo that has no openspec/ #205
  • specsync start can create the change's worktree as an Orca workspace, linked to its issue (worktrees.launcher: orca). #228
  • Add specsync status: the state of your current work, with PR, checks, review and local state. #186
  • specsync 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. #188
  • specsync verify -refs finds commit hashes and request references in your change documents that no longer resolve, for example after a rebase. #196
  • Add specsync 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. #189
  • Add specsync overview for all work across repos, and show every related item in specsync status. #187
  • Add specsync cleanup: list and remove finished worktrees and branches safely, and report the archive follow-up for their changes. #190
Fixed
  • Keep appended links out of dependency sections #198
View complete release details on GitHub →
v0.14.1 Oct 22, 2026
Changed
  • Show where each change's issue, branch, and worktree live #168
  • Cap the length of generated slugs #166
  • specsync agent-help now guides agents toward one branch and worktree per issue, and documents pull's existing -worktree/-worktree-dir flags. #162
  • Support OpenSpec stores as a first-class spec root #173
  • Reject unconsumed CLI arguments instead of silently dropping them #170
  • Restore the topology command and fix stale "soon" badges on the site #179
  • Trim low-value feature cards from the landing page #181
  • Fixed: sync -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. #159
Fixed
  • name every available remedy in the unlinked-commit gate message (#171) 0a976c3
  • restore the topology feature card dropped by the store-support merge (#177) 2d313de
  • site soon-badge clearing didn't consider the local CHANGELOG.md fallback fcfa7f5
View complete release details on GitHub →
v0.14.0 Sep 10, 2026
Changed
  • Adopt an existing issue into an existing change #160
  • Fixed a duplicated "Tasks" heading in synced issue bodies. #155
  • specsync 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
  • Synced issues now show title and task checklist by default; the proposal, original ask, design notes, and discoveries are one click away in collapsed sections instead of pushing the tasks down the page. No content is removed or moved out of the issue. #152
View complete release details on GitHub →