Back to Projects
CRAFT PLATFORM

Taste is now a real skill. Judgment built in. Craft.

View on GitHub
OPEN SOURCE

Below: a real /craft session. muse caught the feeling. alchemist named the physics. Nothing rewritten.

2m 14s · thought for 18s
claude-opus-4-8 · /craft
>
Read 1 file (ctrl+o to expand)
craft:muse(Nail terminal styling for crystallization showcase)
LBash(find ~/dev/personal-site/app/projects/craft-platform -type f | sort)
Read(app/projects/craft-platform/CraftShowcase.tsx)
… +2 tool uses
craft:alchemist(Implementation approach for crystallization terminal)
LBash(grep -n "craft-terminal|accent-green|accent-primary" app/...)
Read(app/globals.css)
… +5 tool uses
thinking…

Agents nailed it!

Muse said keep the chrome minimal - make it feel like watching a real session unfold, not a decorated screenshot.

Alchemist confirmed the build is clean: typed text, real spinners, sequential reveals. No CSS hacks.

Going to build it that way. What do you think?

CrystallizedThis is that terminal. You just watched it design itself.

"The crystallization session isn't a file. It's an event. The terminal needs to read like something is finishing, not something that already finished."

muse · designing this section
HOW CRAFT THINKS

Every /craft invocation reads state and routes to the right action.

/craftStory in progress?Resume storyActive cycle?Pick storyBacklog?Assign to cycleCreate story

No menus. No configuration. State drives everything.

THE ORCHESTRATION

Who calls who

27 agents, seven real flows. Every card in the roster below belongs to one of these - or deliberately belongs to none of them. Each section plays its own diagram the moment you scroll to it.

sequencefile handoffprovenanceunwired
Flow 01 / 06

/craft:story-implement

Every story gets built chunk by chunk. The implementer builds, chunk-validator checks, and the loop doesn't advance until the gates pass - then claims-auditor audits the finished story's claims against what's actually on disk. tester is written and documented, but nothing calls it yet.

chunk 0/4
01
queue
buildimplementer
gate
validatechunk-validator
typechecklintbuildteststokens
collected
claims-auditorAUDITEDsupportedunverifiable
chunk 0/4
queue
buildimplementer
gatechunk-validator
auditorclaims-auditor
01
AUDITED
Flow 02 / 06

/craft:research

Multiple researcher agents chase the same question in parallel, each isolated, each writing its findings straight to disk. research-synthesizer reads every branch file and turns N independent investigations into one answer.

example run/craft:research "how should we architect offline sync?"
researcher×N
research-synthesizer
branch files
the answer and its sources, saved to your repoconflicts kept, not smoothed
Flow 03 / 06

/craft:research-verify

A separate pass, not the same agents grading their own work. verifier instances check the research's claims in parallel, and practitioner-reviewer weighs the verdicts before anything ships as fact.

verifier×N
practitioner-reviewerchecks every verdict against real-world use, not just the docs

Every claim the research made gets checked, independently:

verdicts
confirmedrefutedpartialunverifiable
Flow 04 / 06

/craft:become

become-researcher runs N interviews in parallel - 5 by default, 7 with --deep - each producing a branch file. crystallizer reads all of them and writes something new: an actual agent file. Every card in the Crystallized section below exists because this flow made it.

become-researcher×N
branch files
crystallizerwrites a brand-new agent file
muse, alchemist… ↓
it becomes one of the specialists below
Flow 05 / 06

/craft:review --maze

maze-architect never sees why the code was written - no story, no commit message, just the diff. From that alone it generates 2-4 pointed questions. pr-reviewer-expert answers every one, with evidence, before a PR is trusted.

maze-architectreads the diff blind
it asks the code, directly

Q1"Can a user with role=viewer call this delete endpoint?"

Q2"Does the error path clean up the temp file?"

pr-reviewer-expertanswers each one, with evidence

the PR is only trusted when every answer holds

Flow 06 / 06

/craft:analyze

Five specialists run in sequence, each looking at the same UI through a different lens: usability, then interaction, then creative direction, then visual polish, then a full walkthrough. walkthrough-analyzer also fires automatically whenever a UI cycle completes - nobody has to remember to run it.

qa-analyzerhunts bugs and edge cases
ux-analyzerchecks usability and accessibility
creative-analyzerspots missed wow moments
style-analyzercatches design drift
walkthrough-analyzerautoclicks through like a first-time userruns itself after every UI change ships
On call

/craft:ask

These seven don't hand off to anyone. Ask, they answer. That's the whole system.

musehow do we change this page to feel immersive?
alchemistmockup 3 options of my homepage hero
conductorlook at our proposal for the new /craft:mockup command
doc-writermake the README something a new dev can follow
riffI want to do something with the homepage, I'm just not sure what yet
product-anthropologistwould anybody even use the chat feature?
guideshould this be a fix, a tweak, or a story?
THE AGENTS

27 specialists. Zero shared memory.

Each agent runs in isolated context via Task tool. No shared memory between agents.

Crystallized

Agents produced by /craft:become - minds, not docs.

Isolated contextagents/muse.md
Isolated contextagents/alchemist.md
Isolated contextagents/conductor.md
Isolated contextagents/doc-writer.md
Isolated contextagents/crystallizer.md
Isolated contextagents/riff.md
Plan & Build

From cold codebase to working code.

Isolated contextagents/implementer.md
Isolated contextagents/tester.md
Verification

Nothing ships on anyone's word.

Isolated contextagents/claims-auditor.md
Isolated contextagents/verifier.md
Isolated contextagents/maze-architect.md
Research & Knowledge

Finds out, writes it down, keeps it honest.

Isolated contextagents/researcher.md
Isolated contextagents/guide.md
Analysis

The agents that inspect what was shipped.

Isolated contextagents/qa-analyzer.md
Isolated contextagents/ux-analyzer.md
Isolated contextagents/style-analyzer.md
VALIDATION PIPELINE

7 checks. Every chunk. No exceptions.

After implementation, the chunk-validator agent runs checks sequentially. All 7 must pass before the story is marked complete.

3 4 checks per chunk, all 7 at the finish
chunk-validator agent
// chunk-validator agent - invoked by validate-chunk skill
// Runs checks sequentially, returns structured verdict
CHECKS = [
"TypeScript Strict", // tsc --noEmit
"Lint", // eslint
"No Any Types", // scan changed files
"Build", // next build (story-final only)
"TDD Verification", // verify test files exist
"Tests + Coverage", // vitest (story-final only)
"Design Tokens", // check raw hex vs tokens
]
// Per-chunk: typecheck, lint, any-types, tokens
// Story-final: ALL 7 checks
// Verdict: PASSED | FAILED | PARTIAL
The tradeoff

The gate is absolute. Running all 7 every single chunk is not - next build and the full suite are way too slow to sit through twenty times in a row. So per chunk you get the 4 cheap ones: typecheck, lint, no any types, design tokens. Build and full tests wait for story-final. The cost is real, and I’ll say it plainly: you can get 3 chunks deep before a build break surfaces. Still beats a loop nobody wants to run.

agents/chunk-validator.md
TypeScript Strict
Lint
No Any Types
Build
TDD Verification
Tests + Coverage
Design Tokens

FAILED → refine-chunk. 2+ failures → mandatory learnings capture. 4+ → offer rollback.

THE HOOK SYSTEM

7 lifecycle events - the nervous system of the plugin

Every action flows through hooks. The agent never sees the wiring.

1 The model forgets, a hook doesn’t
hooks.json
{
"hooks": {
"SessionStart": [
{ "hooks": [{ "command": "session-start.sh", "once": true }] },
{ "matcher": "compact", "hooks": [{ "command": "post-compact-reinject.sh" }] }
],
"PreToolUse": [
{ "matcher": "Write|Edit", "hooks": [{ "command": "check-write-permission.py" }] }
],
"PostToolUse": [
{ "matcher": "Write|Edit", "hooks": [{ "command": "update-progress.py" }] }
],
"UserPromptSubmit": [
{ "hooks": [{ "command": "inject-craft-context.sh" }] }
],
"PreCompact": [
{ "hooks": [{ "command": "export-progress.sh" }] }
],
"Stop": [
{ "hooks": [{ "command": "stop-hook-guard.sh" }] }
]
}
}
The tradeoff

I used to write the rules into the prompt and then watch them evaporate. Context gets compacted, the model drifts, and three hours later it’s cheerfully editing a file I told it never to touch. So the rules moved into shell scripts that fire on lifecycle events instead. Not elegant - it’s bash and JSON - but you wire the plumbing once and it’s invisible forever. The write gate is one of these hooks, which is why the agent literally can’t write when the gate is closed. It’s not being obedient. It just has no hands.

hooks/hooks.json
2 Don’t let the chain die at the handoff
stop-hook-guard.sh
#!/bin/bash
# When skill A invokes skill B, A drops a breadcrumb file.
# If the agent tries to stop after B completes, this hook
# reads the breadcrumb and injects "keep going."
BREADCRUMB="${PROJECT_ROOT}.craft/.continuation"
if [ -f "$BREADCRUMB" ]; then
CRUMB_AGE=$(($(date +%s) - $(stat -f %m "$BREADCRUMB")))
if [ "$CRUMB_AGE" -lt 1800 ]; then
ACTION=$(grep '^ACTION:' "$BREADCRUMB" | sed 's/^ACTION: //')
SKILL=$(grep '^SKILL:' "$BREADCRUMB" | sed 's/^SKILL: //')
ARGS=$(grep '^ARGS:' "$BREADCRUMB" | sed 's/^ARGS: //')
rm -f "$BREADCRUMB" # One-shot: consumed on read
echo "{\"systemMessage\": \"DO NOT STOP. Skill chain in progress.
Invoke ${SKILL} with args: ${ARGS}\"}"
exit 0
fi
fi
The tradeoff

Invoking a skill ends the turn. So skill A calls skill B, B finishes, and the chain quietly dies right at the spot where the actual work was supposed to keep going. Now A drops a breadcrumb before it hands off, and the Stop hook finds it and tells the agent: don’t stop, you’re mid-chain. The crumb is one-shot - read once, deleted - with a 30 minute TTL. I’d rather drop a chain now and then than build something that can trap itself in a loop forever.

hooks/scripts/stop-hook-guard.sh

rm -f $BREADCRUMB - One-shot. Consumed on read. If the agent stops mid-chain, this hook catches it and says “keep going.”

UNDER THE HOOD
TypeScriptClaude Code Plugin APICustom Hooks (Python + Bash)YAML State Machine55+ Bash Tests27 Specialized Agents30 Commands11 Skills7-Check Validation Pipeline
KEEP GOING