Bidirectional spec-to-code validation with cross-project references, dependency graphs, and AI-powered generation. Written in Rust. Single binary. 12 languages. VS Code extension.
Quick Start • Spec Format • CLI • VS Code Extension • Cross-Project Refs • GitHub Action • Config • Docs Site
SpecSync validates markdown module specs (*.spec.md) against your source code in both directions:
| Direction | Severity | Meaning |
|---|---|---|
| Code exports something not in the spec | Warning | Undocumented export |
| Spec documents something missing from code | Error | Stale/phantom entry |
| Source file in spec was deleted | Error | Missing file |
| DB table in spec missing from schema | Error | Phantom table |
| Column in spec missing from migrations | Error | Phantom column |
| Column in schema not documented in spec | Warning | Undocumented column |
| Column type mismatch between spec and schema | Warning | Type drift |
| Required markdown section missing | Error | Incomplete spec |
Auto-detected from file extensions. Same spec format for all.
| Language | Exports Detected | Test Exclusions |
|---|---|---|
| TypeScript/JS | export function/class/type/const/enum, re-exports, export * wildcard resolution |
.test.ts, .spec.ts, .d.ts |
| Rust | pub fn/struct/enum/trait/type/const/static/mod |
#[cfg(test)] modules |
| Go | Uppercase func/type/var/const, methods |
_test.go |
| Python | __all__, or top-level def/class (no _ prefix) |
test_*.py, *_test.py |
| Swift | public/open func/class/struct/enum/protocol/actor |
*Tests.swift |
| Kotlin | Top-level declarations (excludes private/internal) | *Test.kt, *Spec.kt |
| Java | public class/interface/enum/record/methods |
*Test.java, *Tests.java |
| C# | public class/struct/interface/enum/record/delegate |
*Test.cs, *Tests.cs |
| Dart | Top-level (no _ prefix), class/mixin/enum/typedef |
*_test.dart |
| PHP | class/interface/trait/enum, public function/const, skips private/protected and __ magic methods |
*Test.php |
| Ruby | class/module, public methods with visibility tracking, attr_accessor/attr_reader/attr_writer, constants |
*_test.rb, *_spec.rb |
| YAML | Top-level mapping keys (anchors, aliases supported) | — |
- uses: CorvidLabs/spec-sync@v4
with:
strict: 'true'
require-coverage: '100'cargo install specsyncDownload from GitHub Releases:
# macOS (Apple Silicon)
curl -sL https://github.com/CorvidLabs/spec-sync/releases/latest/download/specsync-macos-aarch64.tar.gz | tar xz
sudo mv specsync-macos-aarch64 /usr/local/bin/specsync
# macOS (Intel)
curl -sL https://github.com/CorvidLabs/spec-sync/releases/latest/download/specsync-macos-x86_64.tar.gz | tar xz
sudo mv specsync-macos-x86_64 /usr/local/bin/specsync
# Linux (x86_64)
curl -sL https://github.com/CorvidLabs/spec-sync/releases/latest/download/specsync-linux-x86_64.tar.gz | tar xz
sudo mv specsync-linux-x86_64 /usr/local/bin/specsync
# Linux (aarch64)
curl -sL https://github.com/CorvidLabs/spec-sync/releases/latest/download/specsync-linux-aarch64.tar.gz | tar xz
sudo mv specsync-linux-aarch64 /usr/local/bin/specsyncWindows: download specsync-windows-x86_64.exe.zip from the releases page.
cargo install --git https://github.com/CorvidLabs/spec-syncspecsync migrate # Upgrade from 3.x to 4.0.0 (.specsync/ layout)
specsync migrate --dry-run # Preview migration without changes
specsync init # Create specsync.json config
specsync check # Validate specs against code
specsync check --fix # Auto-add undocumented exports as stubs
specsync diff # Show exports added/removed since HEAD
specsync diff HEAD~5 # Compare against a specific ref
specsync coverage # Show file/module coverage
specsync report # Per-module coverage with stale detection
specsync generate # Scaffold specs for unspecced modules
specsync generate --provider auto # AI-powered specs (auto-detect provider)
specsync scaffold auth # Scaffold spec + auto-detect source files
specsync add-spec auth # Add a single spec + companion files
specsync deps # Validate cross-module dependency graph
specsync changelog v3.3.0..v3.4.0 # Generate changelog between git refs
specsync comment --pr 42 # Post spec check summary as PR comment
specsync import github 123 # Import spec from GitHub issue
specsync wizard # Interactive guided spec creation
specsync init-registry # Generate specsync-registry.toml
specsync resolve # Verify spec cross-references
specsync resolve --remote # Verify cross-project refs via GitHub
specsync score # Quality-score your spec files (0–100)
specsync compact --keep 10 # Compact old changelog entries in specs
specsync archive-tasks # Archive completed tasks from tasks.md
specsync view --role dev # View specs filtered by role
specsync merge # Auto-resolve merge conflicts in specs
specsync new auth # Quick-create a minimal spec (auto-detects sources)
specsync stale # Find specs that haven't kept up with code changes
specsync rules # Show configured validation rules
specsync lifecycle status # Show lifecycle status of all specs
specsync lifecycle promote auth # Advance auth spec to next status
specsync lifecycle history auth # View transition history for a spec
specsync lifecycle guard auth # Dry-run: check if guards would pass
specsync lifecycle auto-promote # Promote all specs that pass guards
specsync lifecycle enforce --all # CI: validate lifecycle rules
specsync hooks install # Install agent instructions + git hooks
specsync hooks status # Check what's installed
specsync mcp # Start MCP server for AI agent integration
specsync watch # Re-validate on every file changeSpecs are markdown files (*.spec.md) with YAML frontmatter in your specs directory.
---
module: auth # Module name (required)
version: 3 # Spec version (required)
status: stable # draft | review | stable | deprecated (required)
files: # Source files covered (required, non-empty)
- src/auth/service.ts
- src/auth/middleware.ts
db_tables: # Validated against schema dir (optional)
- users
- sessions
depends_on: # Other spec paths, validated for existence (optional)
- specs/database/database.spec.md
- corvid-labs/algochat@messaging # Cross-project ref (owner/repo@module)
---Every spec must include these ## sections (configurable in specsync.json):
Purpose, Public API, Invariants, Behavioral Examples, Error Cases, Dependencies, Change Log
Note: Requirements (user stories, acceptance criteria) belong in a companion
requirements.mdfile, not inline in the spec. Specs are technical contracts; requirements are product intent. See Companion Files below.
SpecSync extracts the first backtick-quoted name per row and cross-references it against code exports:
## Public API
| Function | Parameters | Returns | Description |
|----------|-----------|---------|-------------|
| `authenticate` | `(token: string)` | `User \| null` | Validates bearer token |
| `refreshSession` | `(sessionId: string)` | `Session` | Extends session TTL |Full spec example
---
module: auth
version: 3
status: stable
files:
- src/auth/service.ts
- src/auth/middleware.ts
db_tables:
- users
- sessions
depends_on:
- specs/database/database.spec.md
---
# Auth
## Purpose
Handles authentication and session management. Validates bearer tokens,
manages session lifecycle, provides middleware for route protection.
## Public API
### Exported Functions
| Function | Parameters | Returns | Description |
|----------|-----------|---------|-------------|
| `authenticate` | `(token: string)` | `User \| null` | Validates a token |
| `refreshSession` | `(sessionId: string)` | `Session` | Extends session TTL |
### Exported Types
| Type | Description |
|------|-------------|
| `User` | Authenticated user object |
| `Session` | Active session record |
## Invariants
1. Sessions expire after 24 hours
2. Failed auth attempts rate-limited to 5/minute
3. Tokens validated cryptographically, never by string comparison
## Behavioral Examples
### Scenario: Valid token
- **Given** a valid JWT token
- **When** `authenticate()` is called
- **Then** returns the corresponding User object
### Scenario: Expired token
- **Given** an expired JWT token
- **When** `authenticate()` is called
- **Then** returns null and logs a warning
## Error Cases
| Condition | Behavior |
|-----------|----------|
| Expired token | Returns null, logs warning |
| Malformed token | Returns null |
| DB unavailable | Throws `ServiceUnavailableError` |
## Dependencies
| Module | Usage |
|--------|-------|
| database | `query()` for user lookups |
| crypto | `verifyJwt()` for token validation |
## Change Log
| Date | Change |
|------|--------|
| 2026-03-18 | Initial spec |specsync [command] [flags]
| Command | Description |
|---|---|
check |
Validate all specs against source code (default). --fix auto-adds missing exports as stubs |
diff |
Show exports added/removed since a git ref (default: HEAD) |
coverage |
File and module coverage report |
report |
Per-module coverage report with stale and incomplete detection |
generate |
Scaffold specs for modules missing one (--provider for AI-powered content) |
scaffold <name> |
Scaffold spec + auto-detect source files + register in registry |
add-spec <name> |
Scaffold a single spec + companion files (requirements.md, tasks.md, context.md, testing.md, and design.md if enabled) |
deps |
Validate cross-module dependency graph (cycles, missing deps, undeclared imports) |
changelog <range> |
Generate changelog of spec changes between two git refs |
comment |
Post spec-sync check summary as a PR comment (same validation pipeline as check). --pr N to post, omit to print |
import <source> <id> |
Import specs from GitHub Issues, Jira, or Confluence |
wizard |
Interactive step-by-step guided spec creation |
resolve |
Verify depends_on references exist. --remote fetches registries from GitHub |
init-registry |
Generate specsync-registry.toml from existing specs |
score |
Quality-score spec files (0–100) with improvement suggestions |
compact |
Compact old changelog entries in spec files. --keep N (default: 10) |
archive-tasks |
Archive completed tasks from companion tasks.md files |
view |
View specs filtered by role (--role dev|qa|product|agent) |
merge |
Auto-resolve git merge conflicts in spec files |
new <name> |
Quick-create a minimal spec with auto-detected source files. --full includes companion files |
stale |
Identify specs that haven't been updated since their source files changed |
rules |
Display configured validation rules and built-in rule status |
migrate |
Upgrade from 3.x to 4.0.0 layout (.specsync/ directory, TOML config). --dry-run to preview, --no-backup to skip |
lifecycle promote <spec> |
Advance spec to next status (draft→review→active→stable) |
lifecycle demote <spec> |
Step back one status level |
lifecycle set <spec> <status> |
Set spec to any status (with transition validation) |
lifecycle status [spec] |
Show lifecycle status of one or all specs |
lifecycle history <spec> |
Show transition history (audit log) for a spec |
lifecycle guard <spec> [target] |
Dry-run guard evaluation — check if transition would pass |
lifecycle auto-promote |
Promote all specs that pass their transition guards. --dry-run to preview |
lifecycle enforce |
CI enforcement — validate lifecycle rules, exit non-zero on violations. --all for all checks |
issues |
Verify GitHub issue references in spec frontmatter. --create to create missing issues |
hooks |
Install/uninstall agent instructions and git hooks (install, uninstall, status) |
mcp |
Start MCP server for AI agent integration (Claude Code, Cursor, etc.) |
init |
Create default specsync.json |
watch |
Live validation on file changes (500ms debounce) |
| Flag | Description |
|---|---|
--strict |
Warnings become errors (recommended for CI) |
--require-coverage N |
Fail if file coverage < N% |
--root <path> |
Project root (default: cwd) |
--provider <name> |
AI provider: auto, anthropic, openai, or command. auto detects installed provider. Without --provider, generate uses templates only. |
--fix |
Auto-add undocumented exports as stub rows in spec Public API tables |
--force |
Skip hash cache and re-validate all specs |
--create-issues |
Create GitHub issues for specs with validation errors (on check) |
--dry-run |
Preview changes without writing files (on compact, archive-tasks, merge) |
--stale N |
Flag specs N+ commits behind their source files (on check) |
--exclude-status <s> |
Exclude specs with the given status. Repeatable |
--only-status <s> |
Only process specs with the given status. Repeatable |
--mermaid |
Output dependency graph as Mermaid diagram (on deps) |
--dot |
Output dependency graph as Graphviz DOT (on deps) |
--full |
Include companion files (on new) |
--json |
Structured JSON output |
| Code | Meaning |
|---|---|
0 |
All checks passed |
1 |
Errors, strict warnings, or coverage below threshold |
Specs can declare dependencies on modules in other repositories using owner/repo@module syntax in depends_on:
depends_on:
- specs/database/database.spec.md # Local reference
- corvid-labs/algochat@messaging # Cross-project referenceEach project publishes a specsync-registry.toml at its root to declare available spec modules:
[registry]
name = "myapp"
[specs]
auth = "specs/auth/auth.spec.md"
messaging = "specs/messaging/messaging.spec.md"
database = "specs/db/database.spec.md"Generate one automatically from existing specs:
specsync init-registry # Uses project folder name
specsync init-registry --name myapp # Custom registry namespecsync resolve # Verify local refs exist
specsync resolve --remote # Also verify cross-project refs via GitHubRemote resolution fetches specsync-registry.toml from each referenced repo and validates that the module exists. Requests are grouped by repo to minimize HTTP calls.
Zero CI cost by default — specsync check validates local refs only (no network). Use --remote explicitly when you want cross-project verification.
When you run specsync generate or specsync add-spec, four companion files are created alongside each spec, plus one opt-in:
| File | Author | Validated? | Purpose |
|---|---|---|---|
{module}.spec.md |
Dev/Architect | Yes — against code | Technical contract |
tasks.md |
Anyone | No | Work coordination |
context.md |
Dev/Agent | No | Architecture notes |
requirements.md |
Product/Design | No | The ask, acceptance criteria |
testing.md |
QA/Dev | No | Test strategy, edge cases, manual checklists |
design.md (opt-in) |
Design/Frontend | No | Layout, component hierarchy, design tokens |
design.md is opt-in — enable it in .specsync/config.toml:
[companions]
design = trueAll scaffolded by SpecSync, all human-filled. Only the spec gets bidirectional validation.
Convention: Requirements (user stories, acceptance criteria) must live in
requirements.md, not as inline## Requirementssections inside the spec. Specs define the technical contract; requirements capture product intent. Inline requirements in non-draft specs produce a warning prompting you to move them to the companion file.
requirements.md — Product requirements and acceptance criteria:
---
spec: auth.spec.md
---
## User Stories
- As a [role], I want [feature] so that [benefit]
## Acceptance Criteria
- [ ] <!-- TODO: define acceptance criteria -->
## Constraints
<!-- Non-functional requirements, performance targets, compliance needs -->
## Out of Scope
<!-- Explicitly excluded from this module's requirements -->tasks.md — Multi-role checkpoint tracking:
---
spec: auth.spec.md
---
## Tasks
- [ ] <!-- Implementation checklist -->
## Gaps
<!-- Uncovered areas, missing edge cases -->
## Review Sign-offs
- **Product**: pending
- **QA**: pending
- **Design**: n/a
- **Dev**: pendingcontext.md — Agent briefing document:
---
spec: auth.spec.md
---
## Key Decisions
<!-- Architectural or design decisions -->
## Files to Read First
<!-- Most important files for understanding this module -->
## Current Status
<!-- What's done, in progress, blocked -->
## Notes
<!-- Free-form notes, links, context -->testing.md — Test strategy and QA checklist:
---
spec: auth.spec.md
---
## Automated Testing
<!-- Test file locations and what they cover -->
## Manual QA Checklist
- [ ] <!-- Manual verification steps -->
## Edge Cases
<!-- Boundary conditions, race conditions, unusual inputs -->design.md (opt-in) — Design and layout documentation:
---
spec: auth.spec.md
---
## Layout
<!-- Page/component layout, responsive breakpoints, positioning -->
## Components
<!-- Component tree, props, slots -->
## Tokens
<!-- Design token overrides from global design system -->
## Assets
<!-- Icons, images, illustrations needed -->These files are designed for team coordination and AI agent context — they give any contributor (human or AI) the full picture of where a module stands.
SpecSync extracts symbols from YAML files (.yml, .yaml) including GitHub Actions workflows, Docker Compose files, and Kubernetes manifests.
What gets extracted:
- Top-level keys — any key at column 0 (e.g.,
name,on,jobs) - Nested children of well-known parents —
jobs.test,services.web,volumes.pgdata, etc. Parents:jobs,services,volumes,networks,secrets,stages,steps,targets,outputs,inputs,permissions,deployments - YAML anchors —
&anchor-namedefinitions
Indentation: Any consistent indentation (2-space, 4-space, or tabs) is supported for nested key extraction.
YAML supports multi-document files separated by --- (common in Kubernetes manifests). SpecSync handles these correctly:
# Multi-document YAML (e.g., k8s manifests)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
---
apiVersion: v1
kind: Service
metadata:
name: my-svc- Top-level keys from all documents are extracted (
apiVersion,kind,metadatafrom both) - The
---separator is not confused with spec frontmatter delimiters — frontmatter parsing only applies to.spec.mdfiles - Duplicate keys across documents are deduplicated in the symbol list
Note: SpecSync's YAML extractor uses regex-based parsing, not a full YAML parser. This means it works without any YAML library dependency but does not interpret YAML semantics like merge keys (
<<: *alias) beyond anchor extraction.
Install from the VS Code Marketplace or search "SpecSync" in the Extensions panel.
code --install-extension corvidlabs.specsync| Feature | Description |
|---|---|
| Inline diagnostics | Errors and warnings mapped to spec files on save |
| CodeLens scores | Quality scores (0–100) displayed inline above spec files |
| Coverage report | Rich webview with file and LOC coverage |
| Scoring report | Per-spec quality breakdown with improvement suggestions |
| Status bar | Persistent pass/fail/error indicator |
| Validate-on-save | Automatic validation with 500ms debounce |
SpecSync: Validate Specs— runspecsync checkSpecSync: Show Coverage— open coverage reportSpecSync: Score Spec Quality— open scoring reportSpecSync: Generate Missing Specs— scaffold specs for unspecced modulesSpecSync: Initialize Config— createspecsync.json
| Setting | Default | Description |
|---|---|---|
specsync.binaryPath |
specsync |
Path to the specsync binary |
specsync.validateOnSave |
true |
Run validation on file save |
specsync.showInlineScores |
true |
Show CodeLens quality scores |
The extension activates automatically in workspaces containing specsync.json, .specsync.toml, or a specs/ directory. Requires the specsync CLI binary to be installed and on your PATH (or configured via specsync.binaryPath).
Available on the GitHub Marketplace. Auto-detects OS/arch, downloads the binary, runs validation.
| Input | Default | Description |
|---|---|---|
version |
latest |
Release version to download |
strict |
false |
Treat warnings as errors |
require-coverage |
0 |
Minimum file coverage % |
root |
. |
Project root directory |
args |
'' |
Extra CLI arguments |
comment |
false |
Post spec drift results as a PR comment (requires pull_request event) |
token |
${{ github.token }} |
GitHub token for posting PR comments (needs write permissions) |
Basic CI check:
name: Spec Check
on: [push, pull_request]
jobs:
specsync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: CorvidLabs/spec-sync@v4
with:
strict: 'true'
require-coverage: '100'With PR comments:
name: Spec Check
on:
pull_request:
types: [opened, synchronize]
jobs:
specsync:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: CorvidLabs/spec-sync@v4
with:
strict: 'true'
comment: 'true'When comment: 'true' is set, SpecSync posts (or updates) a PR comment showing spec drift — added/removed exports since the base branch. The comment is automatically updated on subsequent pushes.
Create specsync.json or .specsync.toml in your project root (or run specsync init):
{
"specsDir": "specs",
"sourceDirs": ["src"],
"schemaDir": "db/migrations",
"requiredSections": ["Purpose", "Public API", "Invariants", "Behavioral Examples", "Error Cases", "Dependencies", "Change Log"],
"excludeDirs": ["__tests__"],
"excludePatterns": ["**/__tests__/**", "**/*.test.ts", "**/*.spec.ts"],
"sourceExtensions": [],
"aiTimeout": 120
}| Option | Type | Default | Description |
|---|---|---|---|
specsDir |
string |
"specs" |
Directory containing *.spec.md files |
sourceDirs |
string[] |
["src"] |
Source directories for coverage analysis |
schemaDir |
string? |
— | SQL schema dir for db_tables validation |
schemaPattern |
string? |
CREATE TABLE regex |
Custom regex for table name extraction |
requiredSections |
string[] |
7 defaults | Markdown sections every spec must include |
excludeDirs |
string[] |
["__tests__"] |
Directories excluded from coverage |
excludePatterns |
string[] |
Common test globs | File patterns excluded from coverage |
sourceExtensions |
string[] |
All supported | Restrict to specific extensions (e.g., ["ts", "rs"]) |
aiCommand |
string? |
— | Custom command for AI generation (reads stdin prompt, writes stdout markdown) |
aiProvider |
string? |
— | AI provider (auto, claude, anthropic, openai, ollama, copilot, etc.) |
aiTimeout |
number? |
120 |
Seconds before AI command times out per module |
# .specsync.toml
specs_dir = "specs"
source_dirs = ["src", "lib"]
required_sections = ["Purpose", "Public API", "Invariants", "Behavioral Examples", "Error Cases", "Dependencies", "Change Log"]
ai_timeout = 120Config resolution order: .specsync/config.toml → .specsync/config.json → .specsync.toml → specsync.json → defaults with auto-detected source dirs.
On multi-agent teams, each contributor may use a different AI provider. To avoid conflicts in the shared config, create a local override file:
# .specsync/config.local.toml (gitignored automatically)
ai_provider = "ollama"
ai_model = "llama3"This file is merged on top of the shared config and only supports ai_* keys. Alternatively, set the SPECSYNC_AI_COMMAND env var or pass --provider on the CLI.
Configure transition guards in specsync.json to enforce quality gates before specs can be promoted:
{
"lifecycle": {
"trackHistory": true,
"guards": {
"review→active": {
"minScore": 70,
"requireSections": ["Public API", "Invariants"]
},
"active→stable": {
"minScore": 85,
"noStale": true,
"requireSections": ["Public API", "Behavioral Examples", "Error Cases"]
},
"*→stable": {
"minScore": 85,
"message": "Stable specs require high quality scores"
}
}
}
}| Guard Option | Type | Description |
|---|---|---|
minScore |
number? |
Minimum spec quality score (0-100) required |
requireSections |
string[] |
Sections that must exist with non-empty content |
noStale |
bool? |
Spec must not be stale (source files ahead of spec) |
staleThreshold |
number? |
Max commits behind when noStale is true (default: 5) |
message |
string? |
Custom message shown when guard blocks transition |
Guard keys use "from→to" format (e.g., "review→active") or "*→to" for wildcard. ASCII arrows (->) also work.
When trackHistory is enabled (default: true), every status transition is recorded in the spec's frontmatter:
lifecycle_log:
- "2026-04-11: draft → review"
- "2026-04-12: review → active"Use specsync lifecycle guard <spec> to dry-run guard evaluation without making changes.
Auto-promote scans all specs and promotes any whose next transition passes all configured guards:
specsync lifecycle auto-promote # promote eligible specs
specsync lifecycle auto-promote --dry-run # preview without modifyingEnforce validates lifecycle rules for CI pipelines (exits non-zero on violations):
specsync lifecycle enforce --all # run all checks
specsync lifecycle enforce --require-status # every spec needs a status field
specsync lifecycle enforce --max-age # flag stale statuses
specsync lifecycle enforce --allowed # check allowed statusesConfigure enforcement rules in specsync.json:
{
"lifecycle": {
"maxAge": {
"draft": 30,
"review": 14
},
"allowedStatuses": ["draft", "review", "active", "stable"]
}
}| Config Key | Type | Description |
|---|---|---|
maxAge |
object |
Maximum days a spec may stay in each status (e.g., "draft": 30) |
allowedStatuses |
string[] |
Restrict specs to these statuses only |
GitHub Action — add lifecycle-enforce: 'true' to the spec-sync action to enforce lifecycle rules in CI:
- uses: CorvidLabs/spec-sync@v4
with:
lifecycle-enforce: 'true'specsync generate scans your source directories, finds modules without spec files, and scaffolds *.spec.md files for each one.
specsync generate # Scaffold template specs for all unspecced modules
specsync generate --provider auto # Use AI to generate filled-in specs from source code
specsync coverage # See what's still missingUses your custom template (specs/_template.spec.md) or the built-in default. Generates frontmatter + stubbed sections with TODOs.
Reads your source code, sends it to an LLM, and generates specs with real content — Purpose, Public API tables, Invariants, Error Cases, all filled in from the code. No manual filling required.
The AI command is resolved in order:
"aiCommand"inspecsync.jsonSPECSYNC_AI_COMMANDenvironment variableclaude -p --output-format text(default, requires Claude CLI)
Any command that reads a prompt from stdin and writes markdown to stdout works:
{ "aiCommand": "claude -p --output-format text" }
{ "aiCommand": "ollama run llama3" }Set "aiTimeout" in specsync.json to control per-module timeout (default: 120 seconds).
The generate command is the entry point for LLM-powered spec workflows:
specsync generate --provider auto # AI writes specs from source code
specsync check --fix # auto-add any missing exports as stubs
specsync check --json # validate, get structured feedback
# LLM fixes errors from JSON output # iterate until clean
specsync check --strict --require-coverage 100 # enforce full coverage in CIEvery output format is designed for machine consumption:
--jsonon any command → structured JSON, no ANSI codes- Exit code 0/1 → pass/fail, no parsing needed
- Spec files are plain markdown → any LLM can read and write them
- Public API tables use backtick-quoted names → unambiguous to extract
// specsync check --json
{ "passed": false, "errors": ["..."], "warnings": ["..."], "specs_checked": 12 }
// specsync coverage --json
{ "file_coverage": 85.33, "files_covered": 23, "files_total": 27, "loc_coverage": 79.12, "loc_covered": 4200, "loc_total": 5308, "modules": [...] }
// specsync diff HEAD~3 --json
{ "added": ["newFunction", "NewType"], "removed": ["oldHelper"], "spec": "specs/auth/auth.spec.md" }specsync check --fix # Add undocumented exports as stub rows
specsync check --fix --json # Same, with structured JSON outputWhen --fix is used, any export found in code but missing from the spec gets appended as a stub row (| \name` | | | TODO |) to the Public API table. If no ## Public API` section exists, one is created. Already-documented exports are never duplicated.
This turns spec maintenance from manual table editing into a review-and-refine workflow — run --fix, then fill in the descriptions.
specsync diff # Changes since HEAD (staged + unstaged)
specsync diff HEAD~5 # Changes since 5 commits ago
specsync diff v2.1.0 # Changes since a tagShows exports added and removed per spec file since the given git ref. Useful for code review, release notes, and CI drift detection.
src/
├── main.rs CLI entry + output formatting
├── ai.rs AI-powered spec generation (prompt builder + command runner)
├── archive.rs Task archival from companion tasks.md files
├── changelog.rs Changelog generation between git refs
├── comment.rs PR comment generation with spec links
├── compact.rs Changelog entry compaction in spec files
├── config.rs specsync.json / .specsync.toml loading
├── deps.rs Cross-module dependency graph validation
├── generator.rs Spec + companion file scaffolding
├── github.rs GitHub API integration (issues, PRs)
├── hash_cache.rs Incremental validation via content hashing
├── hooks.rs Agent instruction + git hook management
├── importer.rs External importers (GitHub Issues, Jira, Confluence)
├── lifecycle.rs Spec status transitions (promote, demote, set, status, history, guard, auto-promote, enforce)
├── manifest.rs Package manifest parsing (Cargo.toml, package.json, etc.)
├── mcp.rs MCP server for AI agent integration (JSON-RPC stdio)
├── merge.rs Auto-resolve merge conflicts in spec files
├── new.rs Quick-create minimal spec with source auto-detection
├── parser.rs Frontmatter + spec body parsing
├── rules.rs Display configured validation rules
├── registry.rs Registry loading, generation, and remote fetching
├── schema.rs SQL schema parsing for column validation
├── scoring.rs Spec quality scoring (0–100, weighted rubric)
├── stale.rs Staleness detection (spec vs source modification)
├── types.rs Data types + config schema
├── validator.rs Validation + coverage + cross-project ref detection
├── view.rs Role-filtered spec viewing (dev, qa, product, agent)
├── watch.rs File watcher (notify, 500ms debounce)
└── exports/
├── mod.rs Language dispatch
├── typescript.rs TS/JS exports
├── rust_lang.rs Rust pub items
├── go.rs Go uppercase identifiers
├── python.rs Python __all__ / top-level
├── swift.rs Swift public/open items
├── kotlin.rs Kotlin top-level
├── java.rs Java public items
├── csharp.rs C# public items
├── dart.rs Dart public items
├── php.rs PHP public items
├── ruby.rs Ruby public items
└── yaml.rs YAML top-level keys
Design: Single binary, no runtime deps. Frontmatter parsed with regex (no YAML library). Language backends use regex, not ASTs — works without compilers installed. Release builds use LTO + strip + opt-level 3.
- Fork, branch (
git checkout -b feat/my-feature), implement cargo test+cargo clippy- Open a PR
- Create
src/exports/yourlang.rs— returnVec<String>of exported names - Add variant to
Languageenum intypes.rs - Wire extension detection + dispatch in
src/exports/mod.rs - Add tests for common patterns