GitHub sync
GitHub is the first-class sync provider. Everything goes through one CLI surface — specweave sync — or the sw:sync skill that wraps it. Never call gh, curl or the GitHub REST API directly from an agent: the CLI owns token resolution, the rate budget, duplicate detection and the bidirectional links.
Connect
specweave sync setup --provider github
The wizard writes sync.github into .specweave/config.json and validates that your token can actually write to the repository. To re-check an existing setup without re-running the wizard:
specweave sync setup --validate
Where the token comes from
Tokens resolve in one documented order, first hit wins:
.specweave/config.jsonprocess.env.GITHUB_TOKEN, thenprocess.env.GH_TOKEN- the project's
.env gh auth token
specweave sync status prints which layer won and which account it belongs to. This matters: a .env token silently outranks your gh login, so a repository you can push to from the terminal can still 404 from SpecWeave.
A 404 on write means the token's account has no write access to owner/repo. GitHub masks permission failures as 404s. Fix the token; do not retry.
Push
specweave sync push # the active increment
specweave sync push 0042 # a specific increment
specweave sync push 0042 --dry-run # preview, write nothing
specweave sync push 0042 --reconcile # fix stale/duplicate milestones first
specweave sync push 0042 --force # push even when nothing looks changed
push runs in a fixed order: tasks.md → the ACs in spec.md → living docs (only if livingDocs is enabled) → the provider write. Then it drains the retry queue through the same entry point.
Push after tasks change, not on every edit.
Pull
specweave sync pull # report external changes, last 7 days
specweave sync pull --since 30 # last 30 days
specweave sync pull --create-increments # import issues as increments (interactive)
pull is a report by default. --create-increments is the import path: it turns selected issues into NNNN-slug increment folders with externalLinks already populated.
Health
specweave sync status # tokens, account, can-push, provider health, retry queue, gaps
specweave sync status --json # one parsable report
specweave sync status --quick # skip network probes
The exit code is 1 when anything needs attention. The JSON report carries providers, github, health, resilience, gaps and hasIssues.
Bidirectional links
A sync is only correct when both directions exist:
- local → external — the issue key lives in
metadata.jsonunderexternalLinks. - external → local — the issue body carries the increment id and the commit sha.
If either side is missing after a push, the link is broken: re-run specweave sync push <id> --force. Never edit externalLinks by hand.
Mapping
| SpecWeave | GitHub |
|---|---|
| Increment | Issue (optionally under a milestone) |
| Acceptance criteria | Checklist in the issue body |
| Tasks | Checklist items, updated on sync push |
complete | Issue closed (when sync is enabled) |
Configuration
{
"sync": {
"enabled": true,
"github": { "enabled": true, "owner": "my-org", "repo": "my-app" },
"settings": { "autoSyncOnCompletion": true }
}
}
sync.enabled is false by default — nothing talks to GitHub until you turn it on.
See also: Jira and Azure DevOps · specweave sync reference