spec-driven workflows

Specification
 
equals Issue.

Write your spec once in openspec/changes/. Run one command. It appears — and stays current — as a GitHub issue. No double-entry. No drift.

openspecspecsyncgithub issues
see how it works
1. write
Create an OpenSpec change in openspec/changes/ — proposal, tasks, specs. This is your source of truth.
2. sync
Run specsync. The binary reads your change, renders it as an issue body with a task checklist, and creates or updates the GitHub issue idempotently.
3. track
The issue lives in GitHub with stage: and priority: labels. Check off tasks in the issue — they sync back to your local change.
cli tool

specsync

One binary. One command. Specs become issues.

specsync is a single self-contained Go binary that depends only on the standard library. It reads OpenSpec changes from your filesystem and projects them as GitHub issues via the gh CLI. No cloud dependencies. No language requirements — it runs in any project that uses OpenSpec.

The sync is idempotent: run it twice, the issue doesn't change. The marker <!-- specsync:change=slug --> in the issue body is the reconciliation key. Task checklists are a monotonic union — checking off items in GitHub flows back to your local change.

  • Idempotent issue creation
  • Two-way task state sync
  • Dry-run preview mode
  • Label management
  • Go stdlib only
  • Reverse: pull issues → local specs
  • Scan, link, trace commands
  • Dogfoods itself
installgo install github.com/androidand/specsync/cmd/specsync@latest

Six reasons your specs and your issues should be the same thing.

No double-entry
Write the spec once. It appears in GitHub. No more maintaining two versions of the same requirement.
Idempotent by design
Run specsync after every change. The issue updates, nothing breaks. The marker comment is the reconciliation key.
Two-way sync
Check tasks in GitHub, they sync back. Write tasks locally, they sync up. Monotonic union — no data loss.
Any language
Single Go binary, stdlib only. Runs in a Python project, a Rust project, or a TypeScript project — doesn't matter.
Dry-run first
specsync -dry-run shows you exactly what will happen before it happens. Safe by default.
Dogfoods itself
Every issue in the specsync repo is generated from an OpenSpec change. The workflow proves itself.

try it now

Write your spec.
Run specsync.

Start with a dry run to see what specsync will do. Then run it for real. Your specs become issues. Your backlog is your spec set.

specsync -dry-run