From craft-skills
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).
npx claudepluginhub alexiolan/craft-skills --plugin craft-skillsThis skill uses the workspace's default tool permissions.
Execute an approved implementation plan using parallel developer agents.
Executes coding tasks from plan documents or prompts: triages input complexity, builds task lists, implements systematically following patterns, verifies with tests. Use to ship complete features efficiently.
Executes coding tasks from plans, specs, or prompts: triages input, scans codebase for patterns/tests, assesses complexity, implements systematically to ship complete features with quality.
Orchestrates adversarial plan-implement-review pipeline by spawning role-specific agents with separate contexts. Run after /brainstorm, /repo-eval, /repo-health, or /doc-health.
Share bugs, ideas, or general feedback.
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, verifies Codex (if needed), and regenerates AGENTS.md (if needed). All state is local to this block — nothing is expected to persist to subsequent blocks.
CRAFT_PROFILE=$(cat .craft-profile 2>/dev/null || echo "claude")
echo "Profile: $CRAFT_PROFILE"
case "$CRAFT_PROFILE" in
*codex*)
# Verify Codex CLI is installed
if ! command -v codex >/dev/null 2>&1; then
echo "ERROR: codex CLI not found in PATH."
echo "The active profile ($CRAFT_PROFILE) requires Codex."
echo "Install: npm i -g @openai/codex"
echo "Then run: codex login"
exit 1
fi
# Regenerate AGENTS.md if missing or stale
CRAFT_SCRIPTS=$(find ~/.claude/plugins -name "sync-agents-md.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
if [[ ! -f "AGENTS.md" ]] || [[ "CLAUDE.md" -nt "AGENTS.md" ]]; then
bash "$CRAFT_SCRIPTS/sync-agents-md.sh" "$PWD"
fi
;;
"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 a codex or 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.
Read the plan and split it into tasks. Identify which tasks can run in parallel (no dependencies) and which must be sequential.
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 / claude+llm | claude+codex / claude+codex+llm |
|---|---|---|
| Data layer (types, services, queries, schemas) | Claude sonnet | Codex (two-tier, see below) |
| UI components (feature/page components, reusable UI) | Claude sonnet | Claude sonnet |
| Integration (wiring, routing, cross-component state) | Claude opus | Claude opus |
| Bulk mechanical fixes (lint/tsc repair sweeps) | Claude sonnet | Codex (default) |
Codex model selection (only when a task is routed to Codex):
Use default for all tasks when authenticated via codex login (ChatGPT auth). Specific models (codex-mini, gpt-5-codex) require an OpenAI API key. See _craft-core/codex-executor.md for details.
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 against Gemma (timed out on single 491-LOC in-place refactors); Qwen3.6 may handle larger files but the threshold has not yet been re-tuned. To check the hint without paying the dispatch cost, you can 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 minor lint issues (import ordering, whitespace artifacts) that are trivially auto-fixable. 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. A non-empty deviations field means the model diverged from the task — 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 .gemma-escalations.log at project root (file name kept for log continuity across model swaps):
<ISO-timestamp> | <task-id> | <llm-status> | <llm-severity> | <reason-category> | <files-touched>
Reason categories (use the most specific that applies):
prop-name-mismatch — model used wrong prop name (e.g. status vs fulfillmentStatus)enum-member-missing — referenced enum/constant member that doesn't existimport-default-vs-named — wrong import style ({X} vs X)missing-barrel-export — imported from domain/X/ui but component not re-exported therewrong-type-shape — passed wrong shape to a typed parammissing-translation-key — used i18n key that doesn't existlint-not-autofixable — lint error eslint --fix couldn't resolvetask-misunderstood — model did wrong thing entirelytruncation — STATUS block missing/malformed (JSON-schema fallback didn't help)other — describe in fieldThis log is read by /reflect periodically to identify patterns worth fixing in llm-implement.sh SYSTEM_PROMPT or develop dispatch rules. Don't worry about parsing precision — just one line per escalation, semicolons fine in description fields.
Clean up: Delete .llm-task-<task-id>.txt
Hard rules:
claude+codex profiles. In claude+ace, the local LLM (Qwen3.6) gets first shot with Sonnet fallback.model parameter explicitly.Dispatching a Codex task:
For each task routed to Codex:
skills/develop/codex-prompt.md:
{{TASK_DESCRIPTION}} — the task text from the plan{{FILE_LIST}} — the file list from the plan for this task{{ARCHITECTURE_DECISIONS}} — relevant architecture decisions from the plan{{PATTERN_REFERENCES}} — 1-2 existing files Codex should mirror (identify by searching the codebase for similar existing files){{SHARED_STATE_CONTENTS}} — current contents of .shared-state.md$PROJECT_ROOT/.codex-prompt-<task-id>.txtCRAFT_SCRIPTS=$(find ~/.claude/plugins -name "codex-dispatch.sh" -path "*/craft-skills/*" -exec dirname {} \; 2>/dev/null | head -1)
bash "$CRAFT_SCRIPTS/codex-dispatch.sh" "$PWD" "<task-id>" "<codex-model>" "$PWD/.codex-prompt-<task-id>.txt"
$PROJECT_ROOT/.codex-output-<task-id>.json and parse the status fieldError handling for Codex tasks:
| Outcome | Action |
|---|---|
exit 0, status DONE | verify .shared-state.md was updated (diff check), proceed |
exit 0, status DONE_WITH_CONCERNS | log concerns from JSON, decide if a fix agent is needed, proceed |
exit 0, status NEEDS_CONTEXT | provide missing context from plan/shared-state, re-dispatch the same task |
exit 0, status BLOCKED | investigate blocker, fix root cause, re-dispatch |
| exit 0, output JSON missing or invalid | dispatch Claude sonnet reconcile agent to review Codex's file changes and update .shared-state.md |
| exit non-zero | dispatch Claude sonnet fallback agent for this specific task, note the fallback in .shared-state.md |
Shared-state reconcile safeguard: After every successful Codex run, diff .shared-state.md before and after the dispatch. If the file was not updated but Codex made file changes, dispatch a sonnet reconcile agent to inspect the changes and write the correct entries to shared state.
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 all agents complete, review .shared-state.md holistically:
If issues found, dispatch targeted fixes to developer agents. Repeat until consistent.
Before running verification, use graph + LLM to review created/modified files from .shared-state.md. Claude should NOT read the implementation files itself — let LLM do the reading.
Run graph tools and LLM bash directly — no dedicated agents for these.
Step A — Check LM Studio (Bash tool, wait for result):
Profile-gated. Only runs when profile includes llm or is claude+ace:
CRAFT_PROFILE=$(cat .craft-profile 2>/dev/null || echo "claude")
case "$CRAFT_PROFILE" in
*llm*|"claude+ace")
CRAFT_SCRIPTS=$(find ~/.claude/plugins -name "llm-agent.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
Step B — LLM review (batch first, fall back to per-file on timeout):
Skip if Step A returned LLM_SKIPPED_BY_PROFILE or LLM_UNAVAILABLE.
B1 — Try the broad multi-file review with a SHORT timeout (90s). Empirically llm-agent.sh with a multi-file scope often times out — but when it succeeds, it can spot cross-file inconsistencies that per-file reviews miss. Try once, fast:
CRAFT_PROFILE=$(cat .craft-profile 2>/dev/null || echo "claude")
case "$CRAFT_PROFILE" in
*llm*|"claude+ace")
CRAFT_SCRIPTS=$(find ~/.claude/plugins -name "llm-agent.sh" -path "*/craft-skills/*" -exec dirname {} \; 2>/dev/null | head -1)
bash "$CRAFT_SCRIPTS/llm-agent.sh" "Review these files for bugs, missing imports, type mismatches, pattern violations, architecture boundary violations, and security/safety issues: [file list from .shared-state.md or graph results]. Be concise." "$PROJECT_ROOT"
;;
*)
echo "LLM_REVIEW_SKIPPED_BY_PROFILE"
;;
esac
Run this with Bash tool timeout: 90000 (90s, NOT the old 300s). If it returns within budget, use the findings.
B2 — Per-file fallback (if B1 timed out or errored). Iterate over the "Created / Modified Files" section in .shared-state.md and run a focused single-file review for each via llm-review.sh (sequential — LM Studio doesn't reliably handle concurrent requests against a single loaded model):
CRAFT_SCRIPTS=$(find ~/.claude/plugins -name "llm-review.sh" -path "*/craft-skills/*" -exec dirname {} \; 2>/dev/null | head -1)
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, security/safety"
done
Each per-file review usually completes in 30–60s. Aggregate findings from all files before triaging.
B3 — Unload model after either B1 success or B2 completion:
bash "$CRAFT_SCRIPTS/llm-unload.sh"
If Step A returned LLM_UNAVAILABLE (but profile includes llm), fall back to reading only integration/wiring files.
If Step A returned LLM_SKIPPED_BY_PROFILE, the graph review in Step C is the only post-develop review — no file-reading fallback.
Step C — Run graph review (while LLM processes):
Load graph MCP tools via ToolSearch (search for "code-review-graph"), then run:
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 C.5 — Codex adversarial review (optional, profile-gated):
Runs only when profile includes codex AND the codex-plugin-cc plugin is installed. This provides a skeptical second-opinion code review from GPT-5-codex on Claude's implementation.
CRAFT_PROFILE=$(cat .craft-profile 2>/dev/null || echo "claude")
case "$CRAFT_PROFILE" in
*codex*)
# Check if codex-plugin-cc is installed (plugin has /codex:* commands)
if [[ -d ~/.claude/plugins/cache/codex-plugin-cc ]] || [[ -d ~/.claude/plugins/codex-plugin-cc ]]; then
echo "ADVERSARIAL_REVIEW_AVAILABLE"
else
echo "ADVERSARIAL_REVIEW_UNAVAILABLE_NO_PLUGIN"
fi
;;
*)
echo "ADVERSARIAL_REVIEW_SKIPPED_BY_PROFILE"
;;
esac
If the check returned ADVERSARIAL_REVIEW_AVAILABLE, invoke the codex-plugin-cc:adversarial-review skill via the Skill tool. Pass the list of changed files from .shared-state.md as the review scope. When the skill returns, capture its findings and include them in the final Step C (Act on findings) triage alongside the graph and LLM review results.
If the plugin is not installed or the profile excludes codex, skip this step silently. This is a bonus, not a dependency — no error, no warning, no prompt to the user.
Step C.6 — Removed (replaced by Step 3.75 design-review below).
Previously this step invoked ui-ux-pro-max opportunistically. It is now replaced by the dedicated design-review skill in Step 3.75, which invokes frontend-design and (conditionally) ui-ux-pro-max deterministically against screenshots rather than just source code.
Step C — Act on findings: If any review (graph, LLM, adversarial) surfaces issues, dispatch targeted sonnet fix agents before proceeding to verification.
Runs only when the implementation touched UI files. Replaces the older opportunistic ui-ux-pro-max invocation in Step 3.5.C.6.
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.8.
Before verification, invoke craft-skills:simplify via the Skill tool on the changed files listed in .shared-state.md. This catches duplication and premature abstractions that slipped past local-LLM reviews and graph analysis — the specific class of miss that pre-implementation prior-art scans can't catch (e.g. a util I typed verbatim that happens to match a shared util the planner didn't flag).
The simplify skill will:
Based on what simplify reports:
Skip this step silently if the simplify skill is unavailable.
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)