| name | develop |
| description | Use when an approved implementation plan exists and is ready to be executed. Initializes shared state, dispatches parallel developer agents, performs integration review, and runs full verification (lint, tsc, format, build). |
Develop
Execute an approved implementation plan using parallel developer agents.
Input
The user input is: $ARGUMENTS
- Plan path (e.g.,
.claude/plans/2026-03-16-pricing-detail-modal.md): Use this plan
- Empty: Auto-detect the most recent
.md file in .claude/plans/ (excluding archive/ and specs/)
If no plan is found, tell the user to run craft-skills:architect or craft-skills:craft first.
Step 0: Pre-flight Check (profile-aware)
Run this as a single self-contained bash block via the Bash tool. It reads the profile marker and verifies LM Studio (if the profile is claude+ace). All state is local to this block — nothing persists to subsequent blocks.
CRAFT_PROFILE=$(cat .craft-profile 2>/dev/null || echo "claude")
echo "Profile: $CRAFT_PROFILE"
case "$CRAFT_PROFILE" in
"claude+ace")
CRAFT_SCRIPTS=$(find ~/.claude/plugins -name "llm-check.sh" -path "*/craft-skills/*" -exec dirname {} \; 2>/dev/null | head -1)
if [[ -z "$CRAFT_SCRIPTS" ]]; then
echo "ERROR: craft-skills scripts directory not found"
exit 1
fi
LLM_STATUS=$(bash "$CRAFT_SCRIPTS/llm-check.sh")
if [[ "$LLM_STATUS" == LLM_UNAVAILABLE* ]]; then
echo "ERROR: $LLM_STATUS"
echo "The active profile ($CRAFT_PROFILE) requires LM Studio."
exit 1
fi
echo "$LLM_STATUS"
;;
esac
Fail loudly if pre-flight fails. No silent fallback — the user explicitly chose the ace profile.
Step 1: Initialize Shared State
Create a fresh .shared-state.md at the project root (delete if one exists from a previous run):
# Shared Agent State
> Auto-generated during implementation. Do not edit manually.
> This file is deleted after a successful build.
## Architecture Decisions
<!-- Key decisions carried over from the plan -->
## Created / Modified Files
<!-- Format: - path/to/file.ts (exports: Name1, Name2) -->
## Shared Types & Interfaces
<!-- Format: - InterfaceName — path/to/types.ts — brief description -->
## Dependencies Added
<!-- Format: - package-name (reason for adding) -->
## Notes & Warnings
<!-- Anything other agents should be aware of -->
Populate Architecture Decisions with key decisions from the plan before dispatching any tasks.
Progress ledger. Also check for a durable .craft-progress.md at the project root. If it exists from a prior run, every task line marked complete is DONE — do not re-dispatch those task-ids; resume with the remaining tasks. If it doesn't exist, create it:
# Craft Progress Ledger
> Durable across context loss. Survives until Step 5 cleanup. One line per task.
Step 2: Dispatch Tasks
Read the plan and split it into tasks. Identify which tasks can run in parallel (no dependencies) and which must be sequential.
Pre-flight plan scan (before dispatching Task 1). Read the plan once and check for (a) tasks that contradict each other or the plan's Architecture Decisions / Global Constraints, and (b) anything the plan mandates that the review rubric would flag as a defect (a test asserting nothing, verbatim-duplicated logic, a boundary violation). If you find any, present them to the user as ONE batched list — each finding beside the plan text that mandates it — and wait for guidance before dispatching. If clean, proceed without comment.
Dispatch tasks to developer agents. Read the agent prompt template from the implementer-prompt.md file in this skill's directory and provide it as context to each agent along with their specific task.
Executor selection per task type (profile-aware):
| Task Type | claude |
|---|
| Data layer (types, services, queries, schemas) | Claude sonnet |
| UI components (feature/page components, reusable UI) | Claude sonnet |
| Integration (wiring, routing, cross-component state) | Claude opus |
| Bulk mechanical fixes (lint/tsc repair sweeps) | Claude sonnet |
Executor selection for claude+ace profile:
| Task Type | Executor |
|---|
| Data layer (types, services, queries, schemas, enums, mappers) | Qwen3.6 via llm-implement.sh |
| UI components (feature components, reusable UI) | Qwen3.6 via llm-implement.sh → Sonnet fallback |
| Integration (wiring, routing, cross-component state) | Claude opus (unchanged) |
Dispatching a local-LLM task (when CRAFT_PROFILE is claude+ace):
For each non-integration task:
-
Classify the task by target file path:
**/data/models/*.ts, **/data/enums/*.ts, **/data/schemas/*.ts, **/data/infrastructure/*Service.ts, **/data/queries/*Queries.ts, **/data/mappers/*.ts → Data layer → Qwen3.6
**/feature/**, **/ui/** → UI component → Qwen3.6 (with Sonnet fallback)
- Tasks the plan explicitly marks as "integration" → Opus agent
- Multi-file tasks within same domain/layer → dispatch as one Qwen3.6 task, up to ~7 files per dispatch for mechanical/pattern-following changes (Qwen3.6 empirical baseline 2026-05-05: 7 files / ~150 LOC clean-impl in ~55s wall time, status DONE with 4-7 minor TS errors typically auto-fixed via Sonnet micro-fix in ~30-60s — total per dispatch ~90s). For non-mechanical tasks (new architecture, complex refactors) keep batches smaller. Cross-layer → split into sub-tasks.
-
Select reference files using graph-first algorithm:
- Use
semantic_search_nodes_tool to find a similar existing file (same type, different domain)
- Use
imports_of on the reference to discover 1-2 key dependencies (max depth 1, max 3 files total)
- Fallback to Glob if graph unavailable
-
Write task file to $PROJECT_ROOT/.llm-task-<task-id>.txt with the task description from the plan. llm-implement.sh auto-loads .claude/reuse-index.md (if present) into the SYSTEM_PROMPT — you do NOT need to copy it into the task file. If the project has no reuse-index, consider suggesting the user run craft-skills:reuse-index once to generate one (it's a one-time, project-agnostic scan; output stays local).
-
Extract allowed file paths from the plan step (the files the task says to create/modify)
-
Dispatch:
CRAFT_SCRIPTS=$(find ~/.claude/plugins -name "llm-implement.sh" -path "*/craft-skills/*" -exec dirname {} \; 2>/dev/null | head -1)
bash "$CRAFT_SCRIPTS/llm-implement.sh" "$PWD/.llm-task-<task-id>.txt" "$PWD" "<allowed-files-comma-separated>" <ref-file-1> <ref-file-2>
Pre-dispatch routing check (routing_hint): The script does a file-size precheck and emits routing_hint: "consider-sonnet" in the output JSON when a single allowed file exceeds 480 LOC or combined ref+allowed exceeds 2500 LOC. Strongly prefer routing such tasks to a Sonnet agent up front instead of dispatching locally — the 480-LOC threshold was empirically validated (timed out on single 491-LOC in-place refactors); Qwen3.6 may handle larger files but the threshold has not been re-tuned. To check the hint without paying the dispatch cost, run a wc -l of the allowed files yourself before calling the script:
total=0; for f in <allowed-files-space-separated>; do
[ -f "$f" ] && total=$((total + $(wc -l < "$f")))
done
echo "$total"
If any single allowed file is >480 LOC, skip the local LLM and dispatch to Sonnet directly. Document the choice in .shared-state.md notes.
-
Parse JSON output and route by status:
| Status | Severity | Action |
|---|
DONE | none | Run auto-fix first (see below), then npx tsc --noEmit + npm run lint. Clean → accept. Remaining errors → dispatch Sonnet micro-fix agent |
DONE_WITH_CONCERNS | minor | Run auto-fix first (see below), then check. Remaining errors → dispatch Sonnet micro-fix agent (sonnet model, inline prompt: "Fix the following lint/tsc errors. Make minimal changes. Reference: {ref-file}. Errors: {lint-output}. Files: {file-list}") |
DONE_WITH_CONCERNS | major | Dispatch Sonnet full redo agent (sonnet model, same task + reference files + local LLM's written files as context) |
NEEDS_CONTEXT | any | Add missing context to task file, re-dispatch to Qwen3.6 (once). Second failure → Sonnet full redo |
BLOCKED | any | Dispatch Sonnet full redo agent |
Auto-fix step (for DONE and DONE_WITH_CONCERNS with severity minor):
Local-LLM output consistently has trivially auto-fixable lint issues (import ordering, whitespace artifacts). Run this before checking for errors — only escalate to Sonnet if auto-fix doesn't resolve them:
npx eslint --fix <changed-files> 2>/dev/null
npx prettier --write <changed-files> 2>/dev/null
-
Update shared state on the local LLM's behalf: parse files_changed, exports_added, notes, and deviations from JSON and append to .shared-state.md. Mandatory: if deviations is non-empty, copy the text into a new entry under ## Notes & Warnings so future agents (and the integration review in Step 3) see it — and review the divergence before continuing.
-
Log dispatch result in shared state under ## LLM Dispatch Log:
- Task <id> (<description>): LLM → <status> [→ SONNET <action>] ✓
-
Log Sonnet escalations (for future local-LLM tuning):
Whenever you escalate to Sonnet (micro-fix or full redo), append a line to .llm-escalations.log at project root:
<ISO-timestamp> | <task-id> | <llm-status> | <llm-severity> | <reason-category> | <files-touched>
Reason categories (pick the most specific): prop-name-mismatch, enum-member-missing, import-default-vs-named, missing-barrel-export, wrong-type-shape, missing-translation-key, lint-not-autofixable, task-misunderstood, truncation, other. One line per escalation; /reflect reads this log to spot patterns worth fixing in the implementer SYSTEM_PROMPT.
-
Clean up: Delete .llm-task-<task-id>.txt
Hard rules:
- In
claude+ace, UI components get the local LLM (Qwen3.6) first shot with Sonnet fallback. Otherwise UI stays on Claude sonnet.
- Integration tasks always stay on Claude opus. Multi-file reasoning is Claude's strength.
- Always specify the
model parameter explicitly on every Claude dispatch — implementers, micro-fix, full-redo, reconcile, and the final whole-branch review (Step 3.9). An omitted model silently inherits the session's tier (usually opus), defeating cost routing.
Each agent MUST:
- Read
.shared-state.md before starting work
- Read the full plan for their task's context
- Read the project's CLAUDE.md for conventions
- Append their outputs (created files, exported types, dependencies) to shared state after completing
- Check if another agent has already created something they need — import and reuse
- Flag any conflicts or ambiguities in Notes & Warnings
Parallelization rules:
- Tasks that create independent files with no imports between them → parallel
- Tasks that depend on types/exports from earlier tasks → sequential
- Data layer tasks (types, service, queries) typically run first
- UI component tasks often run in parallel after data layer is done
- Integration tasks (wiring components together) run last
Implementer status protocol:
Each agent MUST end their work with one of these status codes:
- DONE — Task completed successfully, no concerns
- DONE_WITH_CONCERNS — Task completed but with caveats (describe what and why)
- NEEDS_CONTEXT — Blocked on missing information from another agent's output or the plan
- BLOCKED — Cannot proceed due to an error, conflict, or ambiguity
Two-stage quality approach:
After each agent completes, check their status:
- DONE → Quick spec compliance check: did they follow the plan? Are exports consistent with shared state?
- DONE_WITH_CONCERNS → Review concerns, decide if they need a fix agent or are acceptable
- NEEDS_CONTEXT → Provide the missing context and re-dispatch
- BLOCKED → Investigate the blocker, fix the root cause, then re-dispatch
If issues found during spec compliance check, dispatch a targeted fix agent before proceeding.
After a task's spec-compliance check passes, append one line to .craft-progress.md: - Task <id>: complete (files: <list>; review: clean). Never re-dispatch a task-id already marked complete — this is what lets a compacted controller resume instead of redoing finished parallel work.
Step 3: Integration Review
After all agents complete, review .shared-state.md holistically:
- Duplicate exports or conflicting type definitions
- Cross-references between agent outputs are consistent
- Naming, patterns, and conventions are consistent
- Notes & Warnings section has no unresolved issues
If issues found, dispatch targeted fixes to developer agents. Repeat until consistent.
Step 3.5: Post-Develop Review (consolidated)
Review created/modified files from .shared-state.md with graph + LLM. Claude should NOT read the implementation files itself — let the graph and LLM do the reading. Run graph tools and LLM bash directly — no dedicated agents.
This is one graph pass + one per-file LLM pass + one whole-diff LLM pass — no diff is reviewed twice. (The simplify reuse/architecture focus is folded into the prompts below and the Step 3.9 opus review.)
Review-prompt rules (apply to every review prompt you compose below — LLM, graph, and the Step 3.9 whole-branch review):
- Never instruct a reviewer to ignore a finding or pre-rate its severity ("treat as minor", "the plan chose this"). If you think a finding is a false positive, let it surface and adjudicate it yourself.
- Ask each reviewer to also return a ⚠️ Cannot-verify-from-diff channel: requirements that live in unchanged code or span tasks. Do NOT have the reviewer crawl the codebase to resolve these — you (the controller) hold cross-task context: resolve each ⚠️ item against the plan +
.shared-state.md. A confirmed gap is a failed review → dispatch a fix agent.
- A defect the plan itself mandates is the user's call — surface it, don't wave it through.
Step A — Graph review (always; runs once):
Load graph MCP tools via ToolSearch (search for "code-review-graph"), then run ONCE:
build_or_update_graph_tool — capture new files
get_review_context_tool — auto-detects changed files from git
NEVER use get_architecture_overview_tool, list_communities_tool, or detect_changes_tool. Claude receives only the findings — do not read the implementation files yourself. Filter out false positives about plugins/skills.
Step B — LLM review (profile-gated; runs once per file + once whole-diff):
Check LM Studio first:
CRAFT_PROFILE=$(cat .craft-profile 2>/dev/null || echo "claude")
case "$CRAFT_PROFILE" in
"claude+ace")
CRAFT_SCRIPTS=$(find ~/.claude/plugins -name "llm-review.sh" -path "*/craft-skills/*" -exec dirname {} \; 2>/dev/null | head -1) && curl -s --max-time 2 ${LLM_URL:-http://127.0.0.1:1234} > /dev/null 2>&1 && echo "LLM_AVAILABLE:$CRAFT_SCRIPTS" || echo "LLM_UNAVAILABLE"
;;
*)
echo "LLM_SKIPPED_BY_PROFILE"
;;
esac
If LLM_SKIPPED_BY_PROFILE or LLM_UNAVAILABLE, the graph review (Step A) + the Step 3.9 opus review are the post-develop review — skip to Step C.
B1 — Per-file review (primary). Review EACH changed file once via llm-review.sh, with a focus covering correctness AND reuse/architecture (this absorbs the old simplify pass):
for f in <space-separated-file-paths-from-shared-state>; do
bash "$CRAFT_SCRIPTS/llm-review.sh" "$f" "bugs, missing imports, type mismatches, pattern violations, architecture boundary violations, reuse opportunities (duplicated utils/types/helpers), premature abstractions, security/safety"
done
Each per-file review usually completes in 30–60s.
B2 — Whole-diff review (once, for cross-file issues). Per-file passes miss cross-file inconsistencies. Run ONE broad pass with a 90s budget:
bash "$CRAFT_SCRIPTS/llm-agent.sh" "Review these files together for cross-file inconsistencies, missing imports between them, and type/contract mismatches across files: [file list from .shared-state.md]. Be concise." "$PROJECT_ROOT"
Run with Bash tool timeout: 90000. If it times out, rely on the per-file findings (B1) + the opus whole-branch review (Step 3.9) for cross-file coverage.
B3 — Unload the model:
bash "$CRAFT_SCRIPTS/llm-unload.sh"
Step C — Act on findings:
Aggregate graph + LLM findings; resolve each ⚠️ cannot-verify item yourself against the plan + .shared-state.md. Then:
- Reuse opportunity / fixable defect → dispatch a targeted sonnet fix agent, then re-run lint/tsc.
- Architecture-boundary violation → STOP, report to the user, await guidance.
Step 3.75: Design Review (conditional, deterministic)
Runs only when the implementation touched UI files.
Gate check:
if [ -f .shared-state.md ] && grep -qE '\.(tsx|vue|svelte|jsx)' .shared-state.md; then
echo "UI_CHANGES_DETECTED"
else
echo "NO_UI_CHANGES"
fi
If NO_UI_CHANGES, skip to Step 4.
If UI_CHANGES_DETECTED AND .claude/aesthetic-direction.md exists:
Invoke craft-skills:design-review via the Skill tool. The skill:
- Starts the dev server (if not running)
- Captures screenshots of affected routes (desktop + mobile)
- Dispatches a Haiku-vision agent to compare against
aesthetic-direction.md and the feature's ux-brief.md success criteria (if present)
- Returns PASS / MINOR_ISSUES / MAJOR_ISSUES verdict
Based on the returned next field:
proceed → continue to Step 4 Verification
fix-and-rerun → the skill handles it: dispatches a sonnet fix agent and re-runs the review automatically. Resume Step 4 once the skill reports clean.
escalate → STOP. Report the design-review findings to the user. Do NOT proceed to verification until the user provides guidance (accept regressions, revise brief, revise implementation).
Fallback: if .claude/aesthetic-direction.md does not exist OR design-review skill is unavailable, log: "Design review skipped — no aesthetic direction. Run craft-skills:aesthetic-direction to enable." Continue to Step 3.9.
Step 3.9: Whole-Branch Review (final gate)
After the per-file and graph reviews, run ONE broad review of the entire branch diff on Claude opus (regardless of the implementer tier used). Per-file and per-task reviews structurally miss cross-file and whole-feature defects; this is the deterministic catch-all, and it absorbs the reuse/complexity audit (there is no separate simplify pass in develop).
Generate the diff as a file first so it never enters the controller's context:
BASE=$(git merge-base HEAD @{u} 2>/dev/null || git merge-base HEAD main 2>/dev/null || git rev-parse HEAD~1)
git diff "$BASE" HEAD > .craft-review.diff
Dispatch a single opus reviewer agent pointed at .craft-review.diff plus the plan's Global Constraints, asking for: spec-compliance + quality findings, reuse opportunities / premature abstractions / unnecessary complexity, and the ⚠️ cannot-verify channel (same review-prompt rules as Step 3.5). Collect findings, then dispatch ONE sonnet fix agent with the complete findings list (not one fixer per finding). If a finding is an architecture-boundary violation, STOP and ask the user instead. Then proceed to Step 4.
Step 4: Verification
Iron Law: No completion claims without running these commands AND reading their output.
Run the full verification sequence:
npm run lint — fix any errors via agents, repeat until clean
npx tsc --noEmit — fix any type errors, repeat until clean
npm run format — format the codebase
npm run build — fix any build errors, repeat from appropriate step
If a step fails repeatedly (3+ attempts), stop and ask the user for guidance.
Step 5: Cleanup
After a successful build:
- Delete
.shared-state.md
- Delete
.craft-profile (if it exists — may be missing when develop is invoked standalone)
- Delete
.llm-task-*.txt files (if any remain from local-LLM dispatch)
- Delete
.craft-progress.md and .craft-review.diff (if present)
- Report a summary of all changes made, files created/modified, and any decisions worth noting