From craft-skills
Executes an approved implementation plan by dispatching parallel developer agents, performing integration review, and running full verification including lint, tsc, format, and build.
How this skill is triggered — by the user, by Claude, or both
Slash command
/craft-skills:developThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Execute an approved implementation plan using parallel developer agents.
Execute an approved implementation plan using parallel developer agents.
The user input is: $ARGUMENTS
.claude/plans/2026-03-16-pricing-detail-modal.md): Use this plan.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.
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")
# Verify LM Studio is running
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.
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.
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)Select reference files using graph-first algorithm:
semantic_search_nodes_tool to find a similar existing file (same type, different domain)imports_of on the reference to discover 1-2 key dependencies (max depth 1, max 3 files total)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:
# Quick check before dispatch — sum LOC of allowed files
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:
claude+ace, UI components get the local LLM (Qwen3.6) first shot with Sonnet fallback. Otherwise UI stays on Claude sonnet.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:
.shared-state.md before starting workParallelization rules:
Implementer status protocol: Each agent MUST end their work with one of these status codes:
Two-stage quality approach: After each agent completes, check their status:
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.
After all agents complete, review .shared-state.md holistically:
If issues found, dispatch targeted fixes to developer agents. Repeat until consistent.
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):
.shared-state.md. A confirmed gap is a failed review → dispatch a fix agent.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 filesget_review_context_tool — auto-detects changed files from gitNEVER 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:
Runs only when the implementation touched UI files.
Gate check:
# Detect UI files in .shared-state.md
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:
aesthetic-direction.md and the feature's ux-brief.md success criteria (if present)Based on the returned next field:
proceed → continue to Step 4 Verificationfix-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.
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.
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 cleannpx tsc --noEmit — fix any type errors, repeat until cleannpm run format — format the codebasenpm run build — fix any build errors, repeat from appropriate stepIf a step fails repeatedly (3+ attempts), stop and ask the user for guidance.
After a successful build:
.shared-state.md.craft-profile (if it exists — may be missing when develop is invoked standalone).llm-task-*.txt files (if any remain from local-LLM dispatch).craft-progress.md and .craft-review.diff (if present)npx claudepluginhub alexiolan/craft-skills --plugin craft-skillsExecutes an implementation plan — writes code and tests, runs quality review, and ships a pull request.
Executes implementation plans by dispatching fresh subagents per task, with per-task review and final whole-branch review. Use when tasks are independent and you want fast iteration without human check-ins.
Executes implementation plans by dispatching parallel task-implementer subagents with worktree isolation. Use when running multi-phase plans with independent tasks.