This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
A two-plugin marketplace for Claude Code and CodeBuddy CLIs:
- specode (
plugins/specode/) — a lightweight spec-driven workflow plugin. As of 1.0.0 it is no longer a state machine: it is a thin orchestration shell (壳) that walks a host agent through a phase pipeline (requirements → design → 执行方式 → 执行 → 验收) and, at each phase, delegates the heavy lifting to superpowers skills (brainstorming/writing-plans/subagent-driven-development/executing-plans/verification-before-completion). When superpowers is absent, specode falls back to a specode-native path (first-class, not an afterthought). It produces 3 fixed documents (requirements.md/design.md/implementation-log.md) under the user's specs directory. This is the plugin thisCLAUDE.mddocuments unless stated otherwise. - task-swarm (
plugins/task-swarm/) — a standalone implementation-phase orchestrator (multi-coder fork + reviewer/validator state machine), extracted out of specode in milestone M1. It has its own CLI, state machine, agents, andCLAUDE.md. specode hands off to it only via the user-chosen "委托 task-swarm" option in the 执行方式 selector, with zero import (calls task-swarm's own/task-swarmcommand).
Most implementation referenced here lives under plugins/specode/. The repo root only contains the marketplace manifest (.claude-plugin/marketplace.json, which lists both plugins), the README, the CHANGELOG, and CONTRIBUTING. Plugin internals are listed in README §Architecture — do not re-derive the file tree, read the README.
# Run the test suite (must be from repo root; tests are hermetic and redirect $HOME)
python3 -m pytest plugins/specode/tests/ -v
# Single test file (the lite suite currently covers only resolve_root.py)
python3 -m pytest plugins/specode/tests/test_resolve_root.py -v
# Local plugin install (development)
claude --plugin-dir ./plugins/specode
codebuddy --plugin-dir ./plugins/specodeThere is no lint or typecheck step configured at the repo level.
These are the rules from CONTRIBUTING.md that are easy to violate and expensive to fix. Read CONTRIBUTING.md in full before opening a PR.
Code under plugins/specode/scripts/ MUST use only the Python 3.8+ standard library. Plugin users install via host CLI plugin install; they do not pip install. Tests under plugins/specode/tests/ MAY use pytest (dev dependency only).
Every script under plugins/specode/scripts/ is a CLI invoked from hooks or directly by the host agent via the run.sh wrapper with the absolute $CLAUDE_PLUGIN_ROOT (fallback $CODEBUDDY_PLUGIN_ROOT) path:
sh "${CLAUDE_PLUGIN_ROOT:-${CODEBUDDY_PLUGIN_ROOT}}/scripts/run.sh" \
"${CLAUDE_PLUGIN_ROOT:-${CODEBUDDY_PLUGIN_ROOT}}/scripts/<name>.py" \
<verb> <args...>run.sh probes python3 → python → py (with Windows Store alias-stub skipping) so the script works on any host with Python 3.8+. Bare python3 <name>.py calls fail in most cwds — when adding a new entry point, match the wrapper template used in hooks/hooks.json and commands/spec.md.
assets/templates/*.md are the output of the workflow — the host agent reads them only after deciding what to write. So never put behavioral constraints (rules, "必须", gating checks) into templates: they get stamped into every spec on disk, dilute the signal, and have zero authority over the agent's pre-write decisions.
Behavioral constraints belong in places the agent reads before it generates content:
skills/specode/SKILL.md(always-loaded persona/orchestration rules)commands/spec.md(loaded when the user invokes/spec)skills/specode/references/*.md(selector verbatim examples, path resolution, superpowers wiring)- The
SessionStarthook'sadditionalContextinjection (scripts/spec_hooks.py)
- Scripts are CLIs, not importable modules. Tests invoke them via
subprocess.runthrough therun_scriptfixture intests/conftest.py. - Use the
fake_homefixture to redirect$HOME,XDG_CONFIG_HOME, and clearSPECODE_ROOT. Tests MUST be hermetic — never touch the real~/.specode/or~/.config/specode/.
specode 1.0.0 has almost no runtime logic. The behavior lives in skills/specode/SKILL.md (always-loaded), which drives the host agent through the phase pipeline. At each phase the agent first tries to invoke the matching superpowers skill via the Skill tool; if it's unavailable, it runs the specode-native fallback inline. The phase ↔ skill map:
| phase | superpowers skill (if installed) | specode-native fallback |
|---|---|---|
| requirements (澄清 + 需求) | superpowers:brainstorming |
AskUserQuestion 澄清 wizard + 按模板写 |
| design (可执行计划) | superpowers:writing-plans |
按 design 模板拆 ## Task N + 验证: AC-N + - [ ] TDD 步骤 |
| 执行 | superpowers:subagent-driven-development / executing-plans (or 委托 task-swarm) |
主代理按 design Task 顺序 TDD(红→绿) |
| 验收 | superpowers:verification-before-completion (+ optional requesting-code-review) |
对照 design 测试要点 / AC-N 逐条核验 |
Both superpowers and task-swarm are soft dependencies (run-time only, called via SKILL prose, zero import). specode installed alone must run the whole 启动→coding 完成 loop via the native fallbacks — the fallback path is a first-class peer of the superpowers path, not a footnote.
Whatever the execution engine, a spec always produces exactly these 3, with fixed filenames, fixed location <specsRoot>/<slug>/:
| doc | filename | content |
|---|---|---|
| 需求 | requirements.md |
散文 spec:背景 / 范围(in/out) / 验收 - [ ] AC-N / 开放问题。Plain prose, no formalized requirement clauses. Bug fixes use Current/Expected prose here — there is no separate bugfix.md. |
| 设计 | design.md |
superpowers writing-plans 可执行计划格式:Goal / Architecture / Tech Stack + ## Task N(each with **Files:**, 验证: AC-N back-reference, - [ ] TDD steps). |
| 执行日志 | implementation-log.md |
执行期追加:设计偏离 / 关键决策 / 最终验收小结。 |
The engine only decides who generates the content, never the form/name/location. When delegating to superpowers (whose brainstorming/writing-plans have their own default output paths), the agent does 后置落盘归位: after the skill returns, verify <specsRoot>/<slug>/<fixed-name> exists; if not, mv/rename the skill's actual output into place. This double-保险 keeps the invariant true regardless of whether the skill obeyed the up-front path instruction.
scripts/ member |
Role |
|---|---|
resolve_root.py |
The only business CLI. specsRoot resolution + persistence + spec listing. stdlib-only. Invoked from commands/spec.md via run.sh. |
spec_hooks.py |
The only hook handler: SessionStart injects an advisory discipline reminder via additionalContext and exits 0. Tolerates non-TTY/empty stdin, swallows all exceptions (advisory, never blocks). |
run.sh / run.cmd |
Python interpreter probes (python3 → python → py) — Windows alias-stub handling lives here. |
There is no heavy state-machine package, no launcher indirection, no shared logging module — those were all removed in 1.0.0.
Resolution order (no cwd / ~/specs fallback):
--rootflag orSPECODE_ROOTenv (highest, temporary override)~/.config/specode/config.json.specsRoot(the normal source — read on every activation)- None → first-time setup:
get-rootexits 3;commands/spec.mdthen callsAskUserQuestionfor the user's document directory and callsset-root --root <abs>to persist it. The user-provided directory is used verbatim as the specs root — specode makes no structural assumptions and does no path concatenation.
verbs: get-root [--root P] (exit 0/3), set-root --root <abs> (exit 0/1), list-specs [--root P] (lists subdirs containing requirements.md, one slug per line). Config writes use tempfile + os.replace + fsync (_atomic_write_json).
There is no persistent state file. "Am I in an active spec, and which phase?" is inferred entirely from (a) the current conversation context (which slug this turn is driving) + (b) which fixed docs exist in <specsRoot>/<slug>/ + (c) - [ ] checkbox progress in design.md. This is the 文档即状态 principle — see SKILL.md §续接 for the inference table.
The host CLI fires exactly one hook: SessionStart → run.sh → spec_hooks.py session-start, which emits an advisory additionalContext reminder that specode is available and how to activate it (/spec, /spec continue <slug>, /spec list). No selector guard, no per-turn footer, no logging, no doc-sync nag — all removed in 1.0.0. The hook is advisory only: it never exit 2s and any exception is swallowed.
After design.md is confirmed, the agent calls AskUserQuestion with an adaptive 4-option selector (each option shown only if its engine is installed): 委托 task-swarm / superpowers subagent-driven / superpowers executing-plans / specode 自执行. It is driven by SKILL prose + verbatim examples in references/selectors.md — there is no constant library, no snapshot/drift test, no PreToolUse hard-validation. The "逐字按范例" rule (don't invent or shorten the options) is enforced only by SKILL.md, which is acceptable for the single-user scenario this rewrite targets.
specode does not import task-swarm and does not know its install path. When the user picks "委托 task-swarm", the agent reads design.md's Task list + each Task's **Files:**, mechanically derives a pipeline.yml (shown to the user first), then drives task-swarm via its own /task-swarm command (whose $CLAUDE_PLUGIN_ROOT self-resolves). If task-swarm is absent, it degrades to specode 自执行 or a superpowers execution path. pipeline.yml is a transient artifact only — not one of the 3 fixed products.
Detailed steps are in CONTRIBUTING.md §Release. The two manifests carrying version MUST match or the plugin tag tooling refuses:
plugins/specode/.claude-plugin/plugin.json→"version".claude-plugin/marketplace.json→ the specode entry'sversion(do not touch the task-swarm entry)
Workflow: bump both manifests → rename ## Unreleased in CHANGELOG to ## X.Y.Z (YYYY-MM-DD) + add a fresh ## Unreleased above → run tests → commit + push → claude plugin tag --dry-run plugins/specode → claude plugin tag plugins/specode --push. Tag format is specode--v{version} (annotated). Pushing the tag IS the release — host CLIs fetch the marketplace manifest from GitHub by git tag.
Semver "API surface" for this plugin (1.0.0+) = the /spec subcommand set (/spec <需求> / /spec continue <slug> / /spec list), the SessionStart hook event, the persisted config.json.specsRoot field, and the 3 fixed document filenames. Removing/renaming any of these is major; adding a backwards-compatible capability is minor.
- README.md — what the plugin does, install/usage, the lite architecture map.
- CONTRIBUTING.md — the full version of the conventions above (stdlib rule, CLI wrapper contract, hook advisory rule, hermetic test conventions, release).
- CHANGELOG.md — narrative history; the 1.0.0 entry records the lightweight refactor (what was deleted, the orchestration-shell model, no-read-side-fallback migration). Older entries document the pre-1.0.0 heavy state machine and task-swarm's M1 extraction.
- plugins/specode/skills/specode/SKILL.md + references/ — the runtime behavior spec the host agent follows (phase orchestration, native fallbacks, 执行方式 selector, specsRoot setup, task-swarm bridge). When changing phase order, the selector, or the fixed-product invariant, keep SKILL.md and the matching
references/<topic>.mdin sync.