openspec-sdd
Skill1 starsChanged 56 days agoMITView on GitHub
Use when doing spec-driven work with OpenSpec.
- Installs packages
In this repository67 other files it gives its agents.
- architect-reviewerSkill
- backend-architectSkill
- backend-developerSkill
- code-architectSkill
- codebase-explorerSkill
- code-reviewerSkill
- code-simplifierSkill
- debuggerSkill
- error-detectiveSkill
- fullstack-developerSkill
- git-workflow-managerSkill
- legacy-modernizerSkill
- pragmatic-architectSkill
- prdSkill
- qa-expertSkill
- research-technical-spikeSkill
- sdd-spec-writerSkill
- security-auditorSkill
- supply-chain-securitySkill
- task-decomposition-expertSkill
- technical-debt-managerSkill
- test-engineerSkill
- typescript-proSkill
- architecture-decision-recordsSkill
- hermes-sdd-packagingSkill
- bug-diagnosisSkill
- build-craftSkill
- code-healthSkill
- code-review-checklistSkill
- commit-smartSkill
- context-architectureSkill
- design-explorationSkill
- design-to-htmlSkill
- developer-experience-reviewSkill
- diagram-tripletSkill
- dispatching-parallel-agentsSkill
- document-diataxisSkill
- e2e-testing-patternsSkill
- executing-plansSkill
- module-designSkill
- openspec-apply-changeSkill
- openspec-archive-changeSkill
- openspec-bulk-archive-changeSkill
- openspec-continue-changeSkill
- openspec-exploreSkill
- openspec-ff-changeSkill
- openspec-new-changeSkill
- openspec-onboardSkill
- openspec-proposeSkill
- openspec-sync-specsSkill
- openspec-update-changeSkill
- openspec-verify-changeSkill
- plan-scope-reviewSkill
- project-learningsSkill
- qa-test-plannerSkill
- requirements-claritySkill
- review-structuralSkill
- security-evidence-firstSkill
- agency-invocationSkill
- hermes-sdd-orchestrationSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 103
Write each artifact to resolvedOutputPath using template as the structure.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
OpenSpec — the full spec-driven loop
OpenSpec (Fission-AI, MIT, @fission-ai/openspec) keeps specs, changes and archive
files in openspec/ inside each project. The CLI is the source of truth; the
openspec-* skills are generated by it and drive each phase. This skill is the
orchestrator: which phase, in which order, against which root.
Invocation in Hermes
Hermes gets skills, not slash commands (OpenSpec has no Hermes command adapter). Invoke them by skill name — and the names are NOT the workflow ids:
| Phase | Skill to load |
| think / scope | /openspec-explore |
| propose (all artifacts at once) | /openspec-propose |
| step-by-step scaffolding | /openspec-new-change, /openspec-continue-change, /openspec-ff-change |
| implement tasks | /openspec-apply-change |
| check code against spec | /openspec-verify-change |
| keep change open, update main specs | /openspec-sync-specs, /openspec-update-change |
| finish | /openspec-archive-change, /openspec-bulk-archive-change |
| adopt in an existing codebase | /openspec-onboard |
Other tools spell the same phases differently — read the file the CLI wrote, not
the canonical name: Claude Code /opsx:propose, Cursor /opsx-propose, Codex
$openspec-propose, Gemini CLI /opsx:propose (.toml).
The loop
idea
|
v
[explore]------> thinking partner; never writes code
|
v
[propose]------> proposal.md + specs/<cap>/spec.md + design.md + tasks.md
| (planning ONLY - stop when artifacts exist)
v
[apply]--------> implement tasks/*, tick `- [ ]` -> `- [x]` as each one lands
|
v
[verify]-------> code vs spec; do not claim done without running it
|
v
[archive]------> merges delta specs into openspec/specs/, then
openspec/changes/archive/YYYY-MM-DD-<name>/Rules the workflows themselves enforce — respect them, don't work around them:
proposeauthorizes planning only. Even if the request says "build it", it stops after the artifacts. Implementation is a NEW user request via apply.- Never create
openspec/changes/<name>/by hand. The CLI scaffold (openspec new change "<name>") writes required metadata (.openspec.yaml). explorenever writes code — it may write change artifacts within a confirmed scope, nothing else.- Only mark
- [x]when the specified behavior is fully implemented, not when deferred or partially done. The apply skill pauses on added scope instead of silently narrowing it. - Archive syncs main specs inline; never archive while a sync is in flight.
- When an implementation is finished and verified, ASK the user before archiving + syncing. The user's standing rule: close the loop by requesting permission ('¿archivo el change y sincronizo los specs?') — archive/sync is the final visible action of the loop, never a silent tail. Also check the work was actually spec-driven first: if the change dir doesn't exist for the work (e.g. an ad-hoc fee policy PR), say so instead of inventing an archive.
Pick the right root first
OpenSpec acts on the nearest openspec/ root from the current directory, so cwd
decides what you touch. Before any phase:
cd <project-root> # where its openspec/ lives
openspec context --json # returns root.path, or no_openspec_root
openspec list --json # active changes (work in flight)
openspec list --specs --json # durable capabilities that already exist
openspec status --change "<name>" --jsonopenspec list never shows specs; --specs does. Read a spec in full with
openspec show "<cap>" --type spec before deciding it is already covered.
In a non-interactive session (no TTY) prefer the scriptable path over the
interactive openspec view dashboard:
openspec new change "<name>" # scaffold (never mkdir)
openspec status --change "<name>" --json # schemaName, applyRequires, artifacts, changeRoot, planningHome
openspec instructions <artifact-id> --change "<name>" --json # template + instruction + resolvedOutputPath
openspec instructions apply --change "<name>" --json # contextFiles, progress, tasks, state
openspec validate --all
openspec archive "<name>" --yesWrite each artifact to resolvedOutputPath using template as the structure;
context and rules from the instruction JSON are constraints, never content to
copy in. state from instructions apply is blocked / ready / all_done.
A design.md is conditional (skip when there are no real decisions); specs
is only "skipped" via skip_specs in .openspec.yaml, never by judgment.
For standalone spec repos registered on the machine, openspec store list --json
and then keep --store <id> on every applicable command (sticky for the session).
This machine's setup
- CLI:
~/.local/bin/openspec(npm global, node v26) — v1.13.0. An older 1.7.0 still exists under nvm v22.22.2; PATH prefers~/.local/bin. - Profile:
customwith all 12 workflows (core ships only 6 and omitsverify).openspec config listto check;openspec config profile corereverts.openspec config set workflowsrejects a comma string — it needs a JSON array, so edit~/.config/openspec/config.jsonand re-runopenspec update. - Hermes surfaces them via
skills.external_dirs, entry~/.hermes/openspec-global/.hermes/skills(that dir is anopenspec inited root, purely a skills carrier). Each project also has its own.hermes/skillsfromopenspec init --tools hermes— same 12 names, so the index shows no duplicates. Local-dir skills win collisions. - Projects initialized:
<project-root>/filter(a git root) and<project-root>/gatekeepr. gatekeepr's root is NOT a git repo (tga-backend/andtga-frontend/are), so Hermes never auto-loads its project skills — the global set is what makes the loop work there. - Updating:
npm install -g @fission-ai/openspec@latest, thenopenspec updateinside EVERY root (global carrier + each project). Skill count is profile- and delivery-dependent:updateregenerates exactly the selected workflows.
Verification gates the repo adds on top of OpenSpec
A change can be fully implemented and still fail its own push. gatekeepr's husky hooks run eslint + tsc --noEmit per commit, and per push tsc --noEmit -p tsconfig.test.json plus a diff-scoped test run. That last one is stricter than the typecheck script and catches test-file-only type errors — e.g. import.meta.dir is rejected there (TS1343) while bun run typecheck passes; use __dirname in test files needing a path. Run the repo's own gate (bun run typecheck:test, bun run format:check) before committing instead of discovering it in the pre-push hook.
openspec archivedoes not run prettier. The archived change dir and the new/updated main specs are written as-is; runningbun run formatafterwards and amending the commit is normal, and CI'sformat:checkwill flag it otherwise (measured on gatekeepr PR #86: 7 spec files missing the trailing newline).- In GitHub Actions, a bare binary name in
run:fails with exit 127 becausenode_modules/.binis not on PATH there; other jobs invoke bins via bun/npm scripts. Usebunx <bin>(resolves the installed devDependency) orbun run <script>. - A merged PR with a base that never reached main is a ghost merge. Squashing PR B onto PR-branch A, then squashing A into main onto a different sha, orphans B:
gh pr view 89 --json mergedAtsays MERGED whilegit merge-base --is-ancestor <merge-sha> origin/mainis false, and B's whole diff is missing from the tree. Verify every "merged" PR once againstorigin/main(ancestor check +git cat-file -e origin/main:<file>for its listed files) instead of trusting the GitHub state; recover from the original commit (git checkout <commit> -- <files>) when found missing. gatekeepr lost its whole P2 (request correlation, RED metrics, circuit breaker) this way and it was only noticed by cross-checking a follow-up task against the tree.
Pitfalls verified on this machine
- A main spec that begins with a delta header is silently inert.
openspec/specs/<cap>/spec.mdwhose first line is## ADDED Requirements(a delta archived into the main spec by mistake) makes that capability's requirements invisible tovalidate,listandarchive— andarchiveREFUSES any later change that MODIFIES that capability ("target spec is structurally invalid"). Detect withgrep -rl "^## ADDED Requirements" openspec/specs/*/spec.md; fix by replacing the delta header with## Purpose+## Requirements. gatekeepr had 14 of 75 specs in this state. openspec validate <change>passes while archive would still refuse the delta. Validation of a change does not check that MODIFIED requirement headers exist in the target spec — that surfaces only as anℹ [INFO] ... Archive would refuse this deltaline. Read those INFO lines, not just the pass/fail verdict, before promising a change is archivable. The same applies to using## MODIFIED Requirementsfor a requirement that does not yet exist in the target spec: it must be## ADDED Requirements.- Archiving a change that CREATES a capability leaves the new main spec with
## Purpose\nTBD - created by archiving change <name>. Update Purpose after archive.— write the real purpose right after archiving, or the spec stays unfinished forever. openspec validatewith no argument prints "Nothing to validate" and exits 1 non-interactively; useopenspec validate --all,--changes,--specsor--archived.- Exit code IS a verdict in 1.13.0: any ERROR ⇒ 1, all valid ⇒ 0 (measured). But WARNINGs
don't change it and
ℹ [INFO]lines ("Archive would refuse this delta") appear inside a valid change — readsummary.totals+items[].issues[].level, not just the exit. --all/--changescover only ACTIVE changes plus specs; archived changes are covered by--archived. Passing an archived name in position (validate "2026-01-01-<name>" --type change) resolves the archive dir and reports a FALSE "No deltas found" ERROR.- A new capability whose delta carries
## Purposekeeps that Purpose after archiving; without it, the main spec getsPurpose: TBD - created by archiving change <name>(measured). Putting Purpose in the delta is the cheap way to avoid the post-archive edit. skip_specs: truein.openspec.yamlvalidates a delta-less change with an INFO; it is the legitimate path for refactors/tooling/docs, not an escape hatch from writing scenarios.- An inert main spec (first line a delta header) is NOT silent:
validate --specsfails it with a missing-Purpose/Requirements ERROR andopenspec list --specs --jsonshowsrequirementCount: 0— detect by either, orgrep -rl "^## ADDED Requirements" openspec/specs/*/spec.md.archivethen aborts and changes nothing. openspec updatetakes no--no-animation(init does, update doesn't).openspec init --tools hermesalso refreshes tools already configured in that project (Claude Code, GitHub Copilot, OpenCode,.agents) to the new version, and leaves other tools' pre-existing skills alone.- Legacy
~/.codex/prompts/opsx-*.mdare reported as deferred cleanup and are only deleted withopenspec update --forceonce replacement skills exist. - A non-git project root means no project-local skill discovery in Hermes —
check
git rev-parse --show-toplevelwhen project skills seem missing. external_dirstakes effect in the NEXT session;hermes skills listis the live check (it resolvesopenspec-*fine in a project whose cwd holds a copy).
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

