doctor
Skill0 starsChanged 5 months agoMITView on GitHub
Preflight audit and setup of project readiness for the SDD framework. Runs 10 checks (specs/constitution.md, specs/template.md, plugin installed + enabled across user/project/local settings, capabilities.md, hooks, git, gh, tooling, specialist agents, project type). The `init` mode creates the per-project artifacts (constitution, specs/template.md, capabilities.md, stack-specific hook scripts, settings.json hook entries) directly with file tools — no helper scripts. The root `CLAUDE.md` is user-owned and never read or modified by this skill. Use this skill when the user asks "is my project SDD-ready", "set up SDD", "configure SDD", "why doesn't /sdd:spec work", "init SDD framework", or otherwise indicates they want to start using Spec-Driven Development.
81 other projects use a version of this.
Adopted by
Most recently taken up by
- stunt-double/stuntdouble-mcptheir own version, first seen Nov 8, 2026
- aaroncohn/openspec-conductor-powerupstheir own version, first seen Nov 8, 2026
- hydra-db/hydradb-claude-codetheir own version, first seen Nov 8, 2026
- woosikkim/oh-my-claudecode-slimtheir own version, first seen Nov 8, 2026
- Ubuntu-Buddha/claude-code-stranger-dangertheir own version, first seen Nov 8, 2026
- flopperj/dotfiles-coretheir own version, first seen Nov 4, 2026
Used with
Projects with it also use uninstall, cancel and 10 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
AnthropicSkilluninstall
Uninstall a community skill that was installed via the hub. Confirms before deleting files, refuses to touch first-party plugin skills, and logs every action. Use when the user wants to fully remove a community skill ("uninstall [skill]", "remove this skill") rather than just disable it.
Also in 6 projects that use this
woosikkimSkillcancel
Clear any stale OMC-Slim state
Also in 3 projects that use this
ibahgatSkillmode
Inspect or switch omi operating mode/profile for speed, depth, autonomy, or strict quality gates.
Also in 3 projects that use this
BlockSkillopen
Open markdown documents in Penpal for collaborative review. Use when you want a human to review a document, plan, or research artifact.
Also in 3 projects that use this
QinghongLinSkilleditor
Read analyst.json and detective.json, make all editorial decisions — what the blog argues, which findings matter, narrative arc and section structure. No visual design. Outputs editor.md (prose) and editor.json (structure with edt_xx IDs).
Also in 3 projects that use this
AnthropicSkillstatus
Case status summary by audience — client-facing (plain language), internal (for the professor), or court-ready (formal caption format per local rules). Same facts, different framing and depth. Use when a student needs to update the client, brief the professor, or prepare a court status report.
Also in 15 projects that use this
Other versions81 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 81
- Yeachan-Heo/oh-my-codex★ 34ksame name
- jihe520/MathModelAgent★ 6.2ksame name
- spotify/portal-ai-plugins★ 2.8ksame name
- fakechris/obsidian_vault_pipeline★ 165same name
- NoobyGains/godmode★ 118same name
- Rich627/whatsapp-claude-plugin★ 114same name
- bluzir/claude-code-design★ 102same name
- jjanczur/tyran★ 81same name
- svy04/ballast★ 73same name
- Hainrixz/agente-pagokit★ 68same name
71 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repositoryOne other file it gives its agents.
- CLAUDE.mdCLAUDE.md
The file
Show its rules and text
We split this skill into the rules it gives an agent
22 rules. 0 are common, 5 are distinctive, and 17 are very specific to this project.
0
Common
Most of the 61 edited versions we read keep these.
5
Distinctive
This author's own choices. Worth a look.
17
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 42
Run all 10 checks against the project root (cwd) plus the installed plugin.
- Very specific: line 43
Read/Glob/Grep/Bash to inspect, then assign pass ✅ / warn ⚠️ / fail ❌.
- Distinctive: line 46
Run/build, Conventions, WHAT NOT TO DO).
- Very specific: line 144
Create or repair the per-project artifacts.
- Very specific: line 145
Read seed templates from ${CLAUDE_PLUGIN_ROOT}/skills/doctor/templates/ (fallback $HOME/.claude/plugins/cache/sdd/skills/doctor/templates/).
- Distinctive: line 148
Run these steps in order. Print a one-line status for each artifact (created / skipped / merged).
- Very specific: line 151
Run pwd to lock the project root.
- Distinctive: line 160
When a category offers several candidates, pick the one the project actually configures/uses — e.g.
- Very specific: line 166
constitution: if specs/constitution.md is absent, copy templates/constitution.md.template → specs/constitution.md.
- Very specific: line 169
template: if specs/template.md is absent, copy templates/specs/template.md → specs/template.md verbatim (the {{placeholders}} are filled …
- Very specific: line 199
If specs/capabilities.md already exists, preserve every <!-- user-override --> section byte-for-byte — including its heading and its …
- Very specific: line 202
When you identify a section by its ## Heading, match the heading as a single line only.
- Very specific: line 203
Do NOT let a section's body greedily absorb the next ## heading — each section ends exactly where the next ## begins.
- Very specific: line 212
If the file doesn't exist, take the user-override sections (Task type → routing rules, Custom routing rules, Generated / out-of-band paths) …
- Very specific: line 223
Keep the example block(s) that match the project's tools, adapting the invocation to how the project actually runs the tool (prefer its …
- Distinctive: line 227
Follow the same shape every example uses:
- Very specific: line 250
When you read a project's lint/typecheck script or CI step, use it to learn *which tool and which config* the project uses — then run that …
- Very specific: line 259
After writing, chmod +x the file.
- Very specific: line 260
Never overwrite an existing hook file: If .claude/hooks/typecheck.sh (or lint.sh) already exists, skip writing it — the user owns it.
- Distinctive: line 262
If a category has no configured/runnable tool, write no script for it (and step 5 adds no entry for it).
- Very specific: line 266
Follow reference/settings-merge.md exactly — it is a mechanical procedure.
- Very specific: line 272
Run the check procedure and present the readiness table so the user sees the new state.
“Common” is measured: kept by at least 6 in 10 of the 61 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
SDD Doctor
Audit and auto-setup for the Spec-Driven Development plugin on a target project.
This skill is LLM-driven. There are no Python helpers — you (Claude) perform every check and every file operation yourself, using your own tools. This is deliberate: it lets you adapt to any stack, package manager, or monorepo layout, and it guarantees files land in the project's own directory rather than wherever a script's working directory happened to be.
Two roots — never confuse them
| Root | What it is | How to resolve | What lives here |
| Project root | the user's project you're operating on | your current working directory (pwd) | specs/, .claude/, package.json, the git repo |
| Plugin root | the installed SDD plugin | ${CLAUDE_PLUGIN_ROOT} (fallback $HOME/.claude/plugins/cache/sdd) | bundled templates/, reference/ — read-only |
⛔ The bug this design fixes: every artifact you create (
specs/...,.claude/...) MUST be written under the project root (cwd). Read seed templates from the plugin root. Never write into the plugin root. When in doubt, runpwdand build paths from it explicitly.
Modes
| Mode | What it does | When to use |
check (default) | Report only — 10 checks with statuses ✅/⚠️/❌ | Sanity check, audit |
init | Create/repair per-project artifacts (constitution, specs/template.md, capabilities.md, stack-specific hooks, settings.json) | First-time setup after the plugin is installed |
Extract the mode from the user message: "check" / "audit" / "is ready" / "what's missing" → check; "init" / "setup" / "create" / "generate" / "configure" / "fix" → init. Default to check.
Mode: check
Run all 10 checks against the project root (cwd) plus the installed plugin. For each, use
Read/Glob/Grep/Bash to inspect, then assign pass ✅ / warn ⚠️ / fail ❌.
specs/constitution.md— exists and contains the canonical sections (Tech stack, Run/build, Conventions, WHAT NOT TO DO). Missing file → fail; present but missing sections → warn.specs/template.md— exists with all required fields: Summary, User stories, Acceptance criteria, Edge cases, Open questions, Testing guidelines. Missing → fail; partial → warn.- Plugin installed —
${CLAUDE_PLUGIN_ROOT}/.claude-plugin/plugin.json(fallback$HOME/.claude/plugins/cache/sdd/.claude-plugin/plugin.json) is readable and itsnameissdd. Reportname@version. - Plugin enabled —
sddappears underenabledPlugins(orplugins) in any of three layers:~/.claude/settings.json(user),<project>/.claude/settings.json(project),<project>/.claude/settings.local.json(local). Name which layer(s). Strip any@versionsuffix when matching. Not listed anywhere → warn (may still auto-load). specs/capabilities.md— exists and contains the sections:Specialist agents,Skills,Stack profile,Task type(routing). Missing → fail; partial → warn. AModelcolumn in the routing table and aGenerated / out-of-band pathssection are expected on freshly-initialized files but are optional on legacy files (their absence → warn, not fail; suggest re-runninginit)..claude/settings.jsonhooks — exists, valid JSON, andhooks.PostToolUsecontains an entry whose command references.claude/hooks/typecheck.shor.claude/hooks/lint.sh. Missing file → fail; present but no SDD hook entry → warn.- Git + gh —
.gitexists,git status --porcelain(clean vs dirty),ghon PATH andgh auth statusok. Dirty tree or missing gh → warn. - Tooling — based on the detected stack, confirm the toolchain is installed (e.g. JS/TS:
node_modulespresent; Python:mypy/ruff/pytestreachable). Missing → warn. - Specialist agents — scan
~/.claude/plugins/cache/*/(excluding thesddplugin) foragents/*.md. List a few. None → warn. - Project type — report the detected language/framework and package manager (whatever they are — not limited to a fixed list) and which specialist agents/skills will be routed to. Genuinely undeterminable → warn.
Discover the project's quality tooling (used by check #8/#10 and all of init)
There is no fixed list of supported stacks. New languages and code-quality tools appear constantly — your job is to figure out how this specific project checks its code and reproduce that, whatever language or tool it uses (Kotlin, Swift, Ruby, PHP, C#/.NET, Elixir, Zig, Clojure, a tool released last month — all in scope). Don't pattern-match against a closed catalog; read the project and reason.
The single most reliable signal: what does the project itself run to verify code? Use it to identify the canonical tool and its config — the hook then runs that tool (narrowly, per-file where possible; see init step 4 for the latency rule). Look, in roughly this priority order:
- Declared scripts/tasks —
package.jsonscripts,Makefile/justfile/Taskfile.ymltargets,composer.jsonscripts,mix.exsaliases, Gradle/Maven tasks,cargo/go/dotnetsubcommands. Atypecheck/lint/check/formatscript is the project telling you the canonical invocation — prefer it over a raw tool call. - CI / pre-commit config —
.github/workflows/*.yml,.gitlab-ci.yml,.pre-commit-config.yaml,lefthook.yml, Husky hooks. Whatever the project gates merges on is its quality bar; mirror it. - Tool config files —
tsconfig.json,pyproject.toml[tool.*],biome.json,.eslintrc*,.golangci.yml,checkstyle.xml,.rubocop.yml,phpstan.neon,.editorconfig, etc. Their presence reveals which checkers are configured. - Manifest + lockfile — to identify the language, framework, and package manager (e.g.
pnpm-lock.yaml→pnpm,yarn.lock→yarn,bun.lockb→bun;pom.xml→Maven,gradlew→Gradle wrapper). Detect monorepos (pnpm-workspace.yaml,workspaces,turbo.json,nx.json).
For each category — typecheck (or compile, for statically-typed languages where the compiler
is the type checker) and lint (style/quality/static-analysis) — pick the one canonical
command the project uses. If the project configures no linter, emit no lint hook (don't invent one).
Confirm the tool is actually runnable (on $PATH, via the package manager, or a repo-local wrapper
like ./gradlew) — never wire a command the environment can't execute.
The templates/hooks/*.sh.template files give you worked examples of the hook shape for several
common ecosystems. They are a starting pattern, not the set of what's allowed — when the project
uses something not shown there, write a block for it by analogy (see init step 4).
Report format (check)
# SDD Readiness Report
**Status:** ⚠️ PARTIAL (8/10 checks passed)
**Stack detected:** Next.js 15 + TypeScript strict + Vitest (pnpm)
| # | Check | Status | Detail |
|---|-------|--------|--------|
| 1 | specs/constitution.md | ✅ | 4/4 required sections present |
| 2 | specs/template.md | ✅ | all fields present |
| 3 | Plugin installed | ✅ | sdd@0.7.0 at ~/.claude/plugins/cache/sdd |
| 4 | Plugin enabled | ✅ | enabled in user, project settings |
| 5 | specs/capabilities.md | ✅ | 4 sections present |
| 6 | .claude/settings.json hooks | ❌ | no PostToolUse hooks |
| 7 | Git + gh | ✅ | clean tree, gh ok |
| 8 | Tooling | ✅ | node_modules present |
| 9 | Specialist agents | ✅ | storybook-tester, nextjs-backend-engineer |
| 10 | Project type | ✅ | nextjs detected |
## Next steps
- <one bullet per actionable fix>Overall status: READY (no fail, no warn) / PARTIAL (some warn or 1–2 fail) / NOT_READY
(3+ fail). Next-step guidance:
- READY → "You can run
/sdd:spec feat <description>" - PARTIAL → "Run
/sdd:doctor initto fill in the missing per-project files" - NOT_READY → "If checks 3 or 4 fail, install the plugin first:
claude plugin install https://github.com/JanSzewczyk/spec-driven-development. Otherwise run/sdd:doctor init."
Mode: init
Create or repair the per-project artifacts. Everything is written under the project root (cwd).
Read seed templates from ${CLAUDE_PLUGIN_ROOT}/skills/doctor/templates/ (fallback
$HOME/.claude/plugins/cache/sdd/skills/doctor/templates/).
Run these steps in order. Print a one-line status for each artifact (created / skipped / merged).
0. Confirm roots
Run pwd to lock the project root. Verify the templates directory is readable at the plugin
root. If the templates are missing, stop and tell the user the plugin looks broken.
1. Discover the project's quality tooling
Apply Discover the project's quality tooling (above). Record: language, framework, package manager, monorepo?, and — for typecheck (or compile) and lint — the one canonical command the project uses, confirmed runnable. This drives steps 4–5. Whatever the stack is, this is the same job: find how the project checks code and capture the exact invocation.
When a category offers several candidates, pick the one the project actually configures/uses — e.g. for a JS/TS linter, whichever of Biome / ESLint / oxlint the project depends on (only one); for a compiled language, the build tool's compile task. If a category has no configured tool, skip it.
2. Seed specs/constitution.md and specs/template.md
mkdir -p specs.- constitution: if
specs/constitution.mdis absent, copytemplates/constitution.md.template→specs/constitution.md. If present, leave it untouched (it's the source of truth, edited via/sdd:constitution). - template: if
specs/template.mdis absent, copytemplates/specs/template.md→specs/template.mdverbatim (the{{placeholders}}are filled later by/sdd:spec). If present, skip. - (Legacy migrations, only if the new path is absent:
specs/_constitution.md→specs/constitution.md,specs/_template.md→specs/template.md,.claude/capabilities.md→specs/capabilities.md.) - Never touch the project-root
CLAUDE.md— it is user-owned.
3. Generate specs/capabilities.md
Scan ~/.claude/plugins/cache/*/ for installed capabilities (skip the sdd plugin's own
verification agents). For each plugin: read agents/*.md frontmatter (name + description) and
**/SKILL.md frontmatter (name + description). Then write specs/capabilities.md with these
sections (keep these exact headings — other commands read them):
## Specialist agents (delegate implementation work)+<!-- auto-generated -->— bullet list of discovered agents (- **name** (plugin) — description), or a placeholder if none.## Skills (load into context on demand)+<!-- auto-generated -->— bullet list of skills.## Stack profile+<!-- auto-generated -->— the detected stack as- **key**: value.## Task type → routing rulesand## Custom routing rules— these carry<!-- user-override -->. The routing table includes aModelcolumn (advisory cost tier per task type). Seed the defaults from the template:sonnetfor contract/test/implementation types,haikuforrefactor/generic.opusis reserved for session-level reasoning phases, not task rows.## Generated / out-of-band paths+<!-- user-override -->— glob list of generated / non-hand-authored files that the diff-consuming agents exclude from context and never flag.
Idempotency — get this exactly right (it has bitten us before): re-running init must produce a byte-stable file, not a growing one. Follow these rules:
- The file has two kinds of section: auto-generated (heading immediately followed by
<!-- auto-generated -->) and user-override (heading immediately followed by<!-- user-override -->). Regenerate the auto-generated ones from scratch every run. - If
specs/capabilities.mdalready exists, preserve every<!-- user-override -->section byte-for-byte — including its heading and its trailing blank line. Take its content from the existing file, not the template. - When you identify a section by its
## Heading, match the heading as a single line only. Do NOT let a section's body greedily absorb the next##heading — each section ends exactly where the next##begins. (The old regex implementation backtracked across##boundaries and swallowed auto-generated sections into a fake "title", which is why the file grew on every re-run.) - Preserve exactly one blank line between sections — don't collapse or add separators on re-write.
- Sanity check before writing: the set of
##headings after regeneration must equal the set before (no new duplicates, none lost). Ifinitis run twice with no other change, the second write must be identical to the first.
If the file doesn't exist, take the user-override sections (Task type → routing rules,
Custom routing rules, Generated / out-of-band paths) verbatim from
templates/capabilities.md.template.
4. Generate hook scripts for the tools you found
Generate .claude/hooks/typecheck.sh and .claude/hooks/lint.sh tailored to the command(s) you
discovered in step 1 — for whatever tools the project uses, not a fixed menu.
- Open the matching template (
templates/hooks/typecheck.sh.template/lint.sh.template) and read two things: the header (shebang → theext=line — copy it verbatim; it reads the PostToolUse payload and extractsfile_path) and the worked example blocks below it. - Keep the example block(s) that match the project's tools, adapting the invocation to how the
project actually runs the tool (prefer its declared script/task —
pnpm typecheck, aMakefiletarget,./gradlew checkstyleMain— over a generic call). - If the project uses a tool not shown in the template, write a new block for it by analogy.
Follow the same shape every example uses:
This is the whole contract: gate on the file extension(s) the tool covers, no-op (case "$ext" in <extensions this tool applies to>) command -v <tool-or-runner> >/dev/null 2>&1 || exit 0 # no-op if not runnable if ! <the project's actual check command> 2>&1; then echo "❌ <tool> failed for $file_path" >&2 exit 2 # exit 2 BLOCKS Claude fi ;; esacexit 0) when the tool isn't reachable,exit 2with a message on a real failure. A repo-local wrapper (e.g.[[ -x ./gradlew ]]) counts as runnable. Whole-project checkers (compilers,go vet) may run on the whole module rather than the single file — that's fine. - For tools invoked through a runner (
bundle exec,npx,pnpm exec,poetry run,pipx), checking that the runner exists is not enough — the tool itself may be uninstalled, and the runner would then exit non-zero and falsely block. Probe the actual tool first and no-op if it's absent, e.g.bundle exec rubocop --version >/dev/null 2>&1 || exit 0(the JS examples model this withnpx --no-install --quiet tsc --version). Only after the tool resolves do you run the real check and let its failureexit 2. - Run the narrowest invocation that still catches the error — this hook fires after EVERY edit.
When you read a project's
lint/typecheckscript or CI step, use it to learn which tool and which config the project uses — then run that tool on$file_path, not the whole-repo command verbatim.pnpm lint/make lint/ a CI job lint the entire repo (and may install deps or run tests) — wiring that into a per-edit hook adds seconds to every keystroke-batch and regresses the dev loop. Prefer per-file (eslint "$file_path",ruff check "$file_path",rubocop "$file_path", per-file type-checkers). Fall back to a whole-project run only for tools with no per-file mode (compilers,tsc --noEmit,go vet ./...,cargo check). - Drop the template's instruction-comment block from the output. Replace
{{TOOLS}}with the comma-separated tool names you actually wrote. End the script withexit 0. - After writing,
chmod +xthe file. Sanity-check it parses:bash -n .claude/hooks/<name>.sh. - Never overwrite an existing hook file. If
.claude/hooks/typecheck.sh(orlint.sh) already exists, skip writing it — the user owns it. Still wire settings.json to point at it. - If a category has no configured/runnable tool, write no script for it (and step 5 adds no entry for it). Writing nothing is correct — better than a hook that blocks on a tool that isn't there.
5. Safe-merge .claude/settings.json
Follow reference/settings-merge.md exactly — it is a mechanical procedure. The essentials:
read → parse → STOP and report if malformed (never clobber) → strip only SDD-marked
PostToolUse entries → append the fresh Edit|Write|MultiEdit entry (only for detected tools) →
preserve every other key verbatim → write with 2-space indent + trailing newline.
6. Re-check and report
Run the check procedure and present the readiness table so the user sees the new state.
Idempotency rules (apply throughout init)
- Existing
specs/constitution.md,specs/template.md, and hook scripts are never overwritten. specs/capabilities.mdregenerates auto-sections but preserves<!-- user-override -->.settings.jsonstrips only SDD-marked entries and re-adds them → no duplicates on re-run; all user keys preserved; a malformed file is left untouched.
Notes
- Commands and verification agents are not per-project: they live in the plugin (
commands/,agents/). Once the plugin is installed and enabled (checks 3 + 4), Claude Code auto-discovers every slash command and SDD agent in every project — no per-project copy. CLAUDE.mdis owned by the user: this framework reads and writes onlyspecs/...and the SDD-tagged hook entries in.claude/settings.json. The rootCLAUDE.mdis never touched./sdd:constitutionis the canonical editor forspecs/constitution.md.
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.

