Claude Code Skills and Hooks for Plan Workflow
Replace procedural CLAUDE.md instructions with Claude Code skills (custom slash commands) and hooks (automated enforcement) to make the plan workflow invocable, context-efficient, and enforceable.
Replace procedural CLAUDE.md instructions with Claude Code skills (custom slash commands) and hooks (automated enforcement) to make the plan workflow invocable, context-efficient, and enforceable.
The plan workflow currently lives as ~80 lines of prose instructions in the project's CLAUDE.md. This has three problems:
Always loaded, rarely needed. The plan workflow instructions consume tokens on every session, even when the user is asking about CSS or debugging a test. Skills load on demand — their context cost is zero until invoked.
Guidance without enforcement. CLAUDE.md instructions are suggestions. The agent can skip steps, forget to check off acceptance criteria, or mark a work item done without a --resolve summary. There is no mechanism to catch these omissions. Hooks are deterministic shell scripts that run automatically at lifecycle events — they cannot be skipped.
Not invocable. The user has no structured way to say "start the plan workflow." They rely on the agent having read and internalized the instructions. Skills are explicit entry points: /plan-next starts the workflow, /plan-done completes it.
Skills for guidance, hooks for enforcement. Skills are playbooks that teach the agent how to do something well. Hooks are guardrails that prevent the agent from doing something wrong. The two layers complement each other — skills make the happy path easy, hooks make the failure path visible.
Trim CLAUDE.md, don't duplicate. When a workflow moves to a skill, remove it from CLAUDE.md. The plan command reference stays in plan/CLAUDE.md (the plan-specific instructions file) where it provides contextual guidance. The procedural workflow steps move to skills.
Minimal hook surface. Hooks should check quickly and exit. A Stop hook that runs npx refrakt plan status --format json and parses JSON is fine. A hook that runs a full build is not. Keep hook execution under 5 seconds.
Progressive adoption. Each skill and hook is independently useful. Ship /plan-next first without the Stop hook and it's already an improvement. Add enforcement later. Don't create a monolithic system that must be adopted all-at-once.
Skills are Markdown files in .claude/skills/<name>/SKILL.md with YAML frontmatter. They become slash commands the user can invoke and/or playbooks Claude auto-loads when the task matches.
/plan-next — Find and start the next work itemPurpose: The primary entry point for plan-driven work. Replaces the "Workflow" section of CLAUDE.md.
Trigger: User types /plan-next, or Claude detects a task that involves implementing a work item.
Sequence:
npx refrakt plan next --format json to find the highest-priority ready item with satisfied dependenciesnpx refrakt plan update <id> --status in-progress to claim itsource attribute — read linked specs from plan/spec/ and decisions from plan/decision/doneFrontmatter:
--- name: plan-next description: Find and implement the next refrakt plan work item allowed-tools: Bash(npx refrakt plan *), Read, Glob, Grep ---
Supporting files: The skill directory may include a reference.md with the plan CLI command reference (the content currently in plan/CLAUDE.md). This loads only when the skill is invoked.
/plan-done — Complete a work itemPurpose: The completion checklist, enforced as a sequence. Replaces the "MANDATORY: Work Item Completion Checklist" section of CLAUDE.md.
Trigger: User types /plan-done or /plan-done WORK-XXX. If no ID is given, auto-detects the in-progress item.
Sequence:
npx refrakt plan update <id> --check "criterion text"--resolve summary from the session's actual changes (files modified, decisions made, branch name)npx refrakt plan update <id> --status done --resolve "..."Frontmatter:
--- name: plan-done description: Complete a work item with criteria verification and resolution summary allowed-tools: Bash(npx refrakt plan *), Bash(git *), Read, Glob, Grep ---
/plan-create — Scaffold new plan itemsPurpose: Context-aware creation of specs, work items, decisions, and bugs. Provides guidance on structure and conventions that currently lives in plan/CLAUDE.md.
Trigger: User types /plan-create work "title", /plan-create spec, /plan-create decision, etc.
Behaviour by type:
npx refrakt plan create spec --title "...". Open the file and populate Problem, Design Principles, and body sections.npx refrakt plan create work --title "..." --priority <p>. Prompt for source (which spec does this implement?), milestone, complexity. Populate Acceptance Criteria section with checkboxes.npx refrakt plan create decision --title "...". Populate Context, Options Considered, Decision, Rationale, Consequences sections.npx refrakt plan create bug --title "...". Populate Steps to Reproduce, Expected, Actual sections.Frontmatter:
--- name: plan-create description: Scaffold new plan items (specs, work items, decisions, bugs) allowed-tools: Bash(npx refrakt plan *), Read, Edit, Write ---
Supporting files: A templates.md reference with the canonical section structures for each item type (drawn from plan/CLAUDE.md).
/plan-refine — Review and improve plan contentPurpose: Iterate on specs and decisions before implementation begins. Validate cross-references, identify gaps, suggest improvements.
Trigger: User types /plan-refine (reviews all draft/review items) or /plan-refine SPEC-XXX (reviews a specific item).
Sequence:
npx refrakt plan validate --format json to find structural issuesdraft or review statusFrontmatter:
--- name: plan-refine description: Review plan content for gaps, missing criteria, and structural issues allowed-tools: Bash(npx refrakt plan *), Read, Glob, Grep ---
/plan-status — Quick overviewPurpose: Surface plan state without the user needing to remember the CLI command.
Trigger: User types /plan-status.
Sequence:
npx refrakt plan statusFrontmatter:
--- name: plan-status description: Show plan status overview allowed-tools: Bash(npx refrakt plan *) ---
Hooks are shell commands configured in .claude/settings.json that run automatically at lifecycle events. They provide enforcement that skills alone cannot.
SessionStart — Inject plan contextEvent: Fires when a Claude Code session begins.
Purpose: Give the agent immediate awareness of plan state. Currently the SessionStart hook runs npm run build. Add a second hook to surface active work.
Implementation:
{ "hooks": { "SessionStart": [ { "type": "command", "command": "npm run build 2>&1 | tail -5", "timeout": 120000 }, { "type": "command", "command": "npx refrakt plan status 2>/dev/null || true", "timeout": 15000 } ] } }
Output: The agent sees active/in-progress work items at the start of every session. This provides context without the user needing to ask.
Failure handling: The || true ensures a build failure in the plan package doesn't block session start. The plan status is informational, not critical.
Stop — Verify work item completionEvent: Fires when the agent is about to stop responding (end of turn or session).
Purpose: Catch the scenario where the agent implements changes but forgets to update the work item. This is the most common workflow failure today.
Implementation:
A shell script at .claude/hooks/check-plan-completion.sh:
#!/bin/bash # Check if any in-progress work items have unchecked acceptance criteria status=$(npx refrakt plan next --type all --format json 2>/dev/null) || exit 0 # Find in-progress items in_progress=$(echo "$status" | jq -r '.[] | select(.status == "in-progress")') [ -z "$in_progress" ] && exit 0 # Check for unchecked criteria unchecked=$(echo "$in_progress" | jq -r ' select(.criteria | map(select(.checked == false)) | length > 0) | "\(.id): \(.criteria | map(select(.checked == false)) | length) unchecked criteria" ') if [ -n "$unchecked" ]; then echo "⚠ In-progress work items with unchecked criteria:" echo "$unchecked" echo "" echo "Consider running /plan-done before ending the session." exit 0 # Warn but don't block fi
Hook config:
{ "Stop": [ { "type": "command", "command": ".claude/hooks/check-plan-completion.sh", "timeout": 10000 } ] }
Exit behaviour:
exit 0 — warning only, session can end. The agent sees the warning and may choose to address it.exit 2 — block the session from ending. Reserved for future use if stricter enforcement is desired.The initial implementation should use exit 0 (warn). Blocking session end is aggressive and may frustrate users who intentionally want to pause work mid-item.
Skills and hooks are only available on Claude Code environments that have local filesystem and shell access:
| Feature | CLI | Desktop | VS Code | JetBrains | Web (claude.ai/code) | Mobile |
|---|---|---|---|---|---|---|
| Custom skills | Yes | Yes | Yes | Yes | No | No |
| Hooks | Yes | Yes | Yes | Yes | No | No |
CLAUDE.md | Yes | Yes | Yes | Yes | Yes | Yes |
plan/CLAUDE.md | Yes | Yes | Yes | Yes | Yes | Yes |
The web and mobile versions run on Anthropic's managed cloud infrastructure without access to .claude/skills/ or hook configurations. CLAUDE.md is the only extension mechanism available there.
Don't remove plan/CLAUDE.md. The plan-specific instructions file (plan/CLAUDE.md) serves as the fallback for web/mobile sessions. It contains the command reference, status progressions, content structure templates, and workflow steps — everything the agent needs to follow the plan workflow without skills or hooks.
The root CLAUDE.md plan section can be trimmed to a pointer:
## Plan Project planning uses `@refrakt-md/plan`. See `plan/CLAUDE.md` for workflow details. On CLI/desktop, use `/plan-next` and `/plan-done` skills instead.
This means:
plan/CLAUDE.md provides reference if needed. The root CLAUDE.md is minimal.plan/CLAUDE.md loads when working in the plan/ directory or when plan commands are relevant. No enforcement, but the workflow instructions are available.The tradeoff is maintaining two representations — skills and plan/CLAUDE.md — but plan/CLAUDE.md already exists and is the authoritative reference. The skills are thin wrappers that encode the sequence (what to do in what order), while plan/CLAUDE.md provides the reference (command syntax, valid statuses, content templates). There's minimal duplication because they serve different purposes.
CLAUDE.mdReplace the ## Plan section (~80 lines of workflow instructions, completion checklist, and command reference) with a short pointer:
## Plan Project planning uses `@refrakt-md/plan`. See `plan/CLAUDE.md` for workflow details and command reference. On CLI/desktop, use `/plan-next` and `/plan-done` skills instead.
Everything else in root CLAUDE.md stays: build commands, architecture, conventions, release process, monorepo structure.
plan/CLAUDE.mdKeep as-is. This file is the authoritative reference for the plan system and the fallback for web/mobile sessions. It contains:
On CLI/desktop, this file provides reference material that the skills can lean on. On web/mobile, it's the entire workflow — no skills or hooks, but all the information the agent needs to follow the process.
.claude/ settings.json # Hook configuration hooks/ check-plan-completion.sh # Stop hook script skills/ plan-next/ SKILL.md # Find and start next work item plan-done/ SKILL.md # Complete a work item plan-create/ SKILL.md # Scaffold new plan items templates.md # Section templates for each item type plan-refine/ SKILL.md # Review and improve plan content plan-status/ SKILL.md # Quick status overview
/plan-next skill + SessionStart hook — highest impact, replaces the most CLAUDE.md content/plan-done skill — enforces the completion checklistStop hook — catches forgotten work item updates/plan-create skill — convenience, lower priority/plan-refine and /plan-status skills — nice-to-haveEach step is independently shippable. Step 1 alone is a meaningful improvement.
Once the skills and hooks are proven in this project, they should be packaged as a Claude Code plugin so that anyone using @refrakt-md/plan can install the workflow tooling.
A Claude Code plugin is a directory with a .claude-plugin/plugin.json manifest that bundles skills, hooks, and configuration:
refrakt-plan-workflow/ .claude-plugin/ plugin.json # Manifest skills/ plan-next/SKILL.md # Find and start next work item plan-done/SKILL.md # Complete a work item plan-create/SKILL.md # Scaffold new plan items plan-create/templates.md # Section templates reference plan-refine/SKILL.md # Review plan content plan-status/SKILL.md # Quick status overview hooks/ hooks.json # Hook definitions (SessionStart, Stop) check-plan-completion.sh # Stop hook script
Manifest (plugin.json):
{ "name": "refrakt-plan-workflow", "description": "Claude Code skills and hooks for @refrakt-md/plan workflows", "version": "1.0.0", "author": { "name": "refrakt-md" }, "repository": "https://github.com/refrakt-md/refrakt", "license": "MIT", "skills": "./skills/", "hooks": "./hooks/hooks.json" }
Skills inside plugins are namespaced to avoid conflicts. The slash commands become /refrakt-plan-workflow:plan-next, /refrakt-plan-workflow:plan-done, etc. — or shorter aliases if Claude Code supports them.
Claude Code plugins are distributed through marketplaces — curated catalogs that users subscribe to. There are three paths to get the plugin to users:
1. Official Anthropic marketplace (widest reach)
Submit the plugin for inclusion in the official marketplace. Users install with:
/plugin install refrakt-plan-workflow@claude-plugins-official
This is the best option for community visibility but requires Anthropic review and approval.
2. Refrakt marketplace (self-hosted)
Host a marketplace.json in a refrakt-md GitHub repo (e.g. refrakt-md/claude-plugins) that catalogs refrakt-specific plugins:
{ "name": "refrakt-plugins", "description": "Claude Code plugins for the refrakt ecosystem", "entries": [ { "name": "refrakt-plan-workflow", "description": "Skills and hooks for @refrakt-md/plan workflows", "source": "github", "github": { "owner": "refrakt-md", "repo": "claude-plugins", "path": "plugins/plan-workflow" } } ] }
Users add the marketplace once, then install:
/plugin marketplace add refrakt-md/claude-plugins /plugin install refrakt-plan-workflow@refrakt-plugins
This gives us full control over the catalog without waiting for Anthropic review.
3. npm package (piggyback on existing distribution)
Since @refrakt-md/plan is already an npm package, the plugin could be distributed as a companion npm package (@refrakt-md/claude-plan-workflow) or bundled inside @refrakt-md/plan itself. A marketplace entry can reference an npm source:
{ "name": "refrakt-plan-workflow", "source": "npm", "npm": { "package": "@refrakt-md/claude-plan-workflow", "version": "^1.0.0" } }
Users still install via /plugin install, not npm install — the npm package is just the delivery mechanism.
Start with option 2 (self-hosted marketplace). It's the fastest to set up, gives us full control, and doesn't depend on Anthropic's review process. Once the plugin is stable and has users, submit to the official marketplace (option 1) for broader discovery.
The npm option (3) is worth considering later if we want the plugin version to stay in sync with @refrakt-md/plan releases — same changeset, same version bump, same publish step.
A refrakt user adopting the plan workflow would:
@refrakt-md/plan (the npm package — runes, CLI commands, scanner)npx refrakt plan init (scaffolds plan/ directory and plan/CLAUDE.md)/plugin marketplace add refrakt-md/claude-plugins/plugin install refrakt-plan-workflow@refrakt-plugins/plan-next to start workingSteps 3-4 are the new addition. The plugin gives them the skills and hooks; plan/CLAUDE.md (generated by plan init) gives them the fallback for web/mobile.
Plugins can be installed at different scopes:
.claude/settings.json, committed): The team agrees to use the plugin. New contributors get it automatically when they clone the repo.~/.claude/settings.json): Personal preference, applies to all projects..claude/settings.local.json, gitignored): Trying it out without affecting the team.For a team adopting the plan workflow, project scope is the right default — commit the plugin reference so everyone on the team gets the skills and hooks.
The Stop hook initially warns (exit 0). If experience shows that warnings are insufficient, it could be changed to block (exit 2). This should be a deliberate decision after living with the warning-only mode.
PreToolUse hook for git pushA PreToolUse hook on Bash(git push*) could verify plan consistency before pushing. This is more aggressive than the Stop hook and should only be added if the softer enforcement proves insufficient.
plan init integrationOnce the plugin exists, npx refrakt plan init could prompt the user to install it — or at minimum print instructions. This closes the loop between the npm package (CLI + runes) and the Claude Code plugin (skills + hooks).
--resolve workflow that /plan-done enforces)