A workflow plugin for Claude Code that enforces a context-first, spec-driven, strictly sequential way of working.
> /plugin marketplace add naniiluja/ccf> /plugin install ccf@ccf
FAQ
ccf is a Claude Code plugin with 1 hand-picked skill for development work, indexed on Flowy. Install it with the command on its page. It includes grill-me. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
Repo: naniiluja/ccf
English ยท Tiแบฟng Viแปt ยท ็ฎไฝไธญๆ
A workflow plugin for Claude Code that enforces a context-first, spec-driven, strictly sequential way of working. CCF turns the loose "vibe coding" loop into a disciplined pipeline where the spec is always fresh, every decision is grounded in real docs, and work happens one verifiable slice at a time.
CLAUDE.md + .claude/, kept continuously fresh so every session starts already knowing the project.be/ + fe/ with nested specs) or onboard an existing one, where /ccf:init analyzes the real structure (5 read-only agents) and writes a spec that mirrors it โ no layout forced on you.| Pain in plain Claude Code | What CCF does about it |
|---|---|
| Context "rots" over a long session; the model drifts from the rules | A SessionStart hook re-injects the context-first reminder every start/clear/compact, and re-loads your in-progress task after a compact. |
| The spec silently falls behind the code | Two freshness hooks compare the spec's vs the code's last git commit time and nudge /ccf:updatespec โ at session start and when you stop. |
| Planning slips straight into editing files | A UserPromptSubmit hook hard-blocks /ccf:plan unless you're in plan mode โ planning stays read-only and reviewable. |
| Design decisions made from stale memory | Bundled Context7 + Microsoft Learn MCP servers; CCF prompts cite official docs before writing. |
| Mistakes repeat across sessions | /ccf:updatespec writes two tiers โ project rules to the spec, anti-mistake feedback to system memory (loaded at higher weight). |
| Big-bang features that are hard to review | Plans are a sequential waterfall of vertical slices, each a thin tracer-bullet (DBโserviceโUI) with its own test gate. |
| Tests written loosely (or skipped) under time pressure | An opt-in test discipline โ when on, ccf-implementer designs a contract-level matrix (Equivalence Partitioning + Boundary Value Analysis + decision table) and writes the tests failing-first as part of implement, and a generated Stop-hook gate blocks stopping until the tests actually pass. Ship-fast flows simply don't opt in. |
/plugin marketplace add naniiluja/ccf
/plugin install ccf@ccf
npx @naniiluja/ccf
(runs claude plugin marketplace add + install for you)
claude plugin marketplace add D:/projects/ccf
claude plugin install ccf@ccf
After installing, open Claude Code in your project folder and run /ccf:init.
| Command | What it does |
|---|---|
/ccf:init | Bootstrap a new project (interview โ generate CLAUDE.md + .claude + plan) or onboard an existing one (5 read-only analyzer agents map the real structure). |
/ccf:plan | Create a sequential plan for one feature, grounded in best practices. Requires plan mode (Shift+Tab) โ enforced by a hook. After planning, execute each task with an agent. |
/ccf:check | Verify the implementation against the spec (conformance, conventions, SOLID/OOP, BEโFE cross-check). Read-only. |
/ccf:fix | Disciplined debugging: reproduce โ trace logs/DB step by step โ root cause โ failing test โ minimal fix. No guessing. |
/ccf:updatespec | Update the spec and system memory with this session's lessons (incl. new tools with "when to use"). |
/ccf:cook | Run the whole todo/in-progress backlog in one go: sequential ccf-implementer loop (stop on any red gate), then a batch-verify pass (review + /code-review in parallel, /simplify, re-gate, /ccf:updatespec). Mutually exclusive with auto-verify.mjs --auto-verify. |
Typical flow: /ccf:init โ (plan mode) /ccf:plan โ implement (per task, or the whole backlog via /ccf:cook) โ /ccf:check โ /code-review โ /ccf:updatespec. When the test discipline is ON, ccf-implementer writes the contract-level matrix tests during implement and the verify chain runs them.
Specialized subagents that inherit the host project's tools, MCP servers and skills โ so they can use whatever MCP your project provides (Supabase, Oracle, chrome-devtools, โฆ) and call its skills, with no per-agent allowlist to maintain. Every CCF agent is a leaf โ it carries disallowedTools: Agent, Task so it cannot spawn nested subagents (nested spawning is allowed by default, but the limit is version-dependent: 3 levels by default, 5 in v2.1.172 through v2.1.216, and 1 โ effectively disabled โ in v2.1.217 and v2.1.218; configurable via the CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH env var โ set to 1 to disable NESTED spawning only, i.e. a spawned subagent can no longer spawn a subagent of its own; the harness still spawns a level-1 subagent normally. CCF blocks nested spawning deterministically regardless of that default). The read-only agents (everyone except ccf-implementer) also list Write, Edit, NotebookEdit, so they get the same MCP/skill reach but cannot write files. Parallelism is read-only research only โ file-writing agents never run in parallel on the same feature.
| Agent | Role | Mode |
|---|---|---|
ccf-codebase-analyzer | Analyzes one slice of an existing codebase and reports what exists, proposing no solutions. Fanned out 5-in-parallel by /ccf:init (onboarding slices, whole project) and /ccf:plan (planning slices, scoped to the requested change). CCF commands discover code through this, never the built-in Explore. | read-only |
ccf-best-practice-researcher | Fetches cited best practices from Context7 / MS Learn in an isolated context. | read-only |
ccf-implementer | Implements exactly one plan task: failing test first, then code to meet acceptance criteria. | writes |
ccf-spec-writer | Drafts CLAUDE.md / rules content from a decisions summary, for /ccf:init and /ccf:updatespec; the main thread writes the files. | drafts |
ccf-spec-checker | Fresh-context reviewer โ checks an implementation or critiques a plan, including a premortem / prospective-failure lens. | read-only |
ccf-debugger | Investigates one root-cause hypothesis, follows the correlation ID, verifies against the DB. | read-only |
Commands and agents are prompts (a model can choose to ignore a prompt). Hooks are the only deterministic part of CCF โ .mjs scripts run by node at lifecycle events, so they fire every time regardless of what the model decides. They are no-build, no-dependency, Windows-clean (Node โฅ 18, built-ins only).
| Hook | Event | What it guarantees |
|---|---|---|
| plan-mode-guard | UserPromptSubmit | If a prompt contains /ccf:plan but the session is not in plan mode, it blocks (exit 2) and tells you to enter plan mode. Every other prompt passes through untouched. This is the enforced half of "planning is read-only and reviewed before execution". |
| plan-review-gate | PreToolUse (ExitPlanMode) | In a /ccf:plan session, denies ExitPlanMode (so the plan can't be presented for approval) until the transcript shows a ccf-spec-checker plan review ran. Best-effort on the undocumented transcript shape: any read failure or a non-CCF session passes through, so it never blocks wrongly โ strong enforcement backed by /ccf:plan's step-6 prompt. (The review now includes a premortem lens; the gate mechanism is unchanged.) |
| session-start | SessionStart (startup|clear|compact) | Injects the context-first reminder so the model wakes up already in CCF mode. If CCF-managed, it adds a freshness signal when the code looks newer than the spec, and after a compact/clear it re-loads the in-progress task from .claude/plan/PLAN.md so you resume exactly where you left off. |
| updatespec-nudge | Stop | Purely advisory, never blocks. Four independent clauses: (A) if you edited code this session but ran no tests, it reminds you to verify your work (run the tests / type-check); (B) if the code changed but the spec didn't, it nudges /ccf:check then /ccf:updatespec; (C) if you ran git commit this session but PLAN.md still has tasks not done, it nudges you to mark each done (only after its /ccf:check + /code-review) or fix its status; (D) if an iteration in PLAN.md has every task row closed, it prints the exact scripts/archive-plan.mjs command to retire it. Guards against re-trigger loops via . Default path is single-channel ( only). (default off): add to the command in to also emit the same nudge as (model-facing) alongside (user-facing) โ on a real harness payload, so this stays off in the shipped . |
Freshness heuristic (shared, single source of truth in hooks/lib/freshness.mjs): both freshness-aware hooks compare the last git commit time (git log -1 --format=%ct) of code files against that of spec files (.md under .claude/rules + CLAUDE.md) โ committer time, so it reflects real content change and is immune to mtime churn from checkout/pull/clone. When git can't answer (not a git repo, or a path with no commits yet โ e.g. a freshly /ccf:init-ed project) it falls back to a depth-limited mtime walk that works for any layout (src/, server/, packages/x/src, plugin-style plugins/x/hooks, or code at the root). It is a lightweight nudge, never a hard conclusion โ a content-level "is the spec still accurate?" judgment is left to /ccf:updatespec.
Why hooks are auto-loaded, not declared: like commands/agents/MCP, hooks load automatically from the standard hooks/hooks.json location โ current Claude Code (v2.1.x) auto-discovers it. Do not add a "hooks" field to plugin.json pointing back at the standard path: that loads the file twice and fails with Duplicate hooks file detected. The manifest.hooks field is only for additional hook files at a non-standard path.
The plugin bundles 2 MCP servers (plugin scope, auto started/stopped by Claude Code):
https://learn.microsoft.com/api/mcp (remote HTTP, no auth required).https://mcp.context7.com/mcp (remote HTTP, works out of the box without a key).Context7 rate limit: the plugin runs Context7 without an API key (free rate limit). If you hit a rate limit, get a free key at context7.com/dashboard, set the
CONTEXT7_API_KEYenv var, and restart Claude Code.
/ccf:updatespec records lessons in two places with different purposes:
CLAUDE.md + .claude/rules/) โ loaded as a user message, lower weight. Holds project rules: conventions, architecture, tech-stack, tooling.~/.claude/projects/<path>/memory/) โ loaded into the system prompt, not down-weighted, so Claude follows it more strongly. Holds anti-mistake feedback + user preferences across sessions โ helps Claude repeat fewer mistakes.MEMORY.md is a pure index โ only its first 200 lines or 25KB load each session, so keep it lean; the strongest tier is feedback (always with its Why).Principle: no duplication. A rule in CLAUDE.md that keeps getting forgotten โ write a feedback memory that reinforces it (with the "why"), rather than copying its content.
A proactive /compact <hint> beats letting auto-compact fire (when context has "rotted" the model is at its least sharp). After you compact, CCF's session-start hook (matcher compact) auto re-loads the in-progress task from .claude/plan/PLAN.md, restoring the right work context so you don't have to paste it back.
/ccf:init and /ccf:plan produce one plan in .claude/plan/ (a PLAN.md index + task-NNN-*.md files). Each task is a thin vertical slice โ a tracer-bullet crossing the layers it touches (DB + service + UI), ordered thinnest โ richest, each as spec โ failing test โ implement. Every task has exactly one predecessor and names the test gate that must be green before the next slice starts. This is what makes "strictly sequential" concrete and reviewable.
PLAN.md stays scoped to the current iteration. When every task in an iteration is done, it is retired into ARCHIVE.md (its task files into .claude/plan/archive/). This cuts both ways on purpose: a closed row left in PLAN.md is counted as live work by the session-start and Stop hooks, while deleting the history would strip ccf-spec-checker's premortem of the real past failures it anchors its predictions to. So the rule is archive, never delete.
Retirement is detected automatically, applied deliberately. The Stop hook notices a fully-closed iteration and prints the exact command; node "<plugin-root>/scripts/archive-plan.mjs" previews it (writing nothing, and naming any row still holding an iteration open) and --apply performs it โ rewriting both files and git mv-ing the task files, staged but never committed. The mutation is not automated on purpose: a hook fires with no human in the loop, and a wrong detection there would silently rewrite your plan and your history.
grill-me) โ the shared requirements-interview engine the commands invoke via the Skill tool; hidden from the / menu (user-invocable: false)..mjs run directly with node โ no build step, no dependency, Windows-clean; shared helpers (freshness, plan parsing, context-usage, review-trace, git-trace, verify-trace, verify-chain, output-style, explore-guide, implementer-verify) live in hooks/lib/.scripts/archive-plan.mjs) โ same no-build/no-dependency rules as a hook, but nothing invokes it automatically. This is where an action that mutates your files belongs, so its blast radius stays bounded by you choosing to run it.{{...}}-placeholder files (root/ always, backend/ + frontend/ when fullstack) that /ccf:init instantiates.See plugins/ccf/ for details. Requires Node โฅ 18 for the hooks.
MIT
This project was first released in the LINUX DO community โ thanks to the community members for their support and feedback.
.claude/
.claude-plugin/
marketplace.json
plan/
archive/
ARCHIVE.md
task-001-prompt-hygiene.md
task-002-path-scoped-rules-docs.md
task-003-verify-work-nudge.md
task-004-settings-json-attribution.md
task-005-testing-tmpl-matrix-discipline.md
task-006-grillme-init-probe-fold.md
task-007-ccf-test-command.md
task-008-test-gate-hook-template.md
task-009-wire-optin-plan-implementer-checker.md
task-010-in-review-status.md
task-011-stop-hook-status-nudge.md
task-012-context-guard-warn-mode.md
task-013-context-guard-hard-block.md
task-014-context-guard-spec-sync.md
task-015-memory-protocol-instruction.md
task-016-memory-protocol-doc-sync.md
task-017-agent-rules-inject-hook.md
task-018-ccf-implementer-body-harden.md
task-019-spec-docs-counts-sync.md
task-020-premortem-lens.md
task-021-premortem-docs-sync.md
task-022-subagent-tool-inheritance.md
task-023-docs-sync.md
task-024-context-guard-compact-boundary.md
task-024a-context-guard-live-verify.md
task-025-explore-guide-inject-hook.md
task-025a-explore-guide-live-verify.md
task-026-explore-guide-docs-sync.md
task-027-right-size-slices.md
task-028-auto-verify-chain.md
task-028a-auto-verify-live-verify.md
task-031-nested-spawn-guard.md
task-032-cook-command.md
task-032a-cook-live-verify.md
task-033-advisor-goal-docs.md
task-034-subagentstop-verify-gate.md
task-034a-subagentstop-live-verify.md
task-035-drop-ccf-command-prefix.md
task-036-style-and-model-choice.md
task-037-spawn-depth-and-await.md
task-038-stop-channel-and-rename.md
task-039-background-spawn-investigation.md
task-040-compact-hint-split.md
task-041-dual-channel-stop-and-io-net.md
task-043-archive-plan-script.md
task-044-plan-codebase-discovery.md
task-045-prompt-standard-plan-backbone.md
task-046-prompt-standard-implement-verify.md
task-047-prompt-standard-init-fix-agents.md
task-048-prompt-standard-release.md
task-049-latch-hardening.md
task-050-templates-standard.md
PLAN.md
rules/
architecture.md
coding-conventions.md
components.md
git-workflow.md
hooks.md
prompt-standard.md
testing.md
tooling.md
tests/
context-budget.mjs
context-budget.test.mjs
.gitattributes
.github/
workflows/
release.yml
.gitignore
bin/
ccf-bootstrap.mjs
CLAUDE.md
LICENSE
package-lock.json
package.json
plugins/
ccf/
.claude-plugin/
plugin.json
.mcp.json
agents/
ccf-best-practice-researcher.md
ccf-codebase-analyzer.md
ccf-debugger.md
ccf-implementer.md
ccf-spec-checker.md
ccf-spec-writer.md
commands/
check.md
cook.md
fix.md
init.md
plan.md
updatespec.md
hooks/
agent-rules-inject.mjs
auto-verify.mjs
context-guard.mjs
explore-guide-inject.mjs
hooks.json
implementer-verify-gate.mjs
lib/
agent-match.mjs
agent-match.test.mjs
archive.mjs
archive.test.mjs
context-usage.mjs
context-usage.test.mjs
explore-guide.mjs
explore-guide.test.mjs
freshness.mjs
freshness.test.mjs
git-trace.mjs
git-trace.test.mjs
implementer-verify.mjs
implementer-verify.test.mjs
io.mjs
io.test.mjs
output-style.mjs
output-style.test.mjs
plan.mjs
plan.test.mjs
review-trace.mjs
review-trace.test.mjs
verify-chain.mjs
verify-chain.test.mjs
verify-trace.mjs
verify-trace.test.mjs
plan-mode-guard.mjs
plan-review-gate.mjs
session-start.mjs
updatespec-nudge.mjs
README.md
scripts/
archive-plan.mjs
skills/
grill-me/
SKILL.md
templates/
backend/
.claude/
rules/
api-design.md.tmpl
backend-conventions.md.tmpl
data-layer.md.tmpl
CLAUDE.md.tmpl
frontend/
.claude/
rules/
component-design.md.tmpl
frontend-conventions.md.tmpl
state-management.md.tmpl
CLAUDE.md.tmpl
root/
.claude/
hooks/
hooks.json.tmpl
lib/
test-gate-core.mjs
test-gate-core.test.mjs
test-gate.mjs.tmpl
plan/
PLAN.md.tmpl
task-template.md.tmpl
rules/
architecture.md.tmpl
coding-conventions.md.tmpl
debugging.md.tmpl
error-handling.md.tmpl
git-workflow.md.tmpl
logging.md.tmpl
tech-stack.md.tmpl
testing.md.tmpl
tooling.md.tmpl
settings.json.tmpl
settings.json.tmpl.md
CLAUDE.md.tmpl
README.md
README.vi.md
README.zh-CN.md
tsconfig.jsonยฉ 2026 Flowy ยท Free and open source
Built for Claude Code ยท Not affiliated with Anthropic
stop_hook_activesystemMessage--dual-channel-stopupdatespec-nudge.mjshooks.jsonadditionalContextsystemMessageStophooks.json| auto-verify | Stop | Opt-in (default off) and the only CCF Stop hook that can block. Enable by adding --auto-verify to the auto-verify.mjs command in hooks.json. When a task is in-review, this session changed code, and no ccf-spec-checker review has run yet, it returns decision: "block" (the "ralph loop") with a reason that drives the main loop through the verify chain โ /ccf:check โ /code-review โ (run the project's test command if the test discipline is on) โ /ccf:updatespec only when both come back clean. Guards against loops via stop_hook_active; best-effort, any error exits silently. |
| context-guard | UserPromptSubmit | When the session transcript shows context has crossed ~40% of the model window โ capped at an absolute ~300k tokens, since 40% of a 1M-native window (Opus/Sonnet 4.x) would be unreachable before auto-compact โ i.e. the "dumb zone", it surfaces a proactive /compact warning (with a ready-made hint pre-filled from your active task). Default = warn, non-blocking: the advice reaches both you (systemMessage) and the model (additionalContext) every turn. Opt into hard-block by adding --hard-block to the context-guard.mjs command in hooks.json โ it then blocks (exit 2) any over-threshold prompt until you compact, with an escape hatch (prefix the prompt with /compact, or include ccf:override). Best-effort: if it can't read the transcript it stays silent. |
| agent-rules-inject | SubagentStart | Output styles modify only the main loop and aren't inherited by subagents, so a spawned file-writing ccf-implementer could violate the coding rules. At spawn this hook injects (via additionalContext) a directive to read & obey the project rules (.claude/rules/* + CLAUDE.md) plus the active output style's coding rules (persona/tone/emoji excluded), then self-check. Only the writer agent gets it (read-only agents are a no-op); best-effort, never blocks the spawn. |
| explore-guide-inject | SubagentStart (Explore) | CCF doesn't own the built-in Explore subagent's prompt, so at spawn this hook injects (via additionalContext) a short, language-agnostic, LSP-conditional exploration directive: prefer semantic navigation (the LSP tool โ workspaceSymbol/goToDefinition/findReferences/documentSymbol, falling back when no server exists) plus ripgrep-backed Grep and Glob, and read whole files only after locating the region. Best-effort, never blocks the spawn. |
| implementer-verify-gate | SubagentStop (ccf-implementer) | Opt-in (default off), child-scoped. Enable by adding --enforce-tests to the implementer-verify-gate.mjs command in hooks.json. When a spawned ccf-implementer's final message carries no TEST-RESULT: evidence (the pinned Return-format line โ a real result OR the prose-only TEST-RESULT: n/a (no test surface)), it returns decision: "block" telling the implementer to add the line and finish again; this only keeps the SUBAGENT running, it does not affect the main loop. Defensive-by-design: SubagentStop's loop-guard/transcript_path shape are not yet observed on a real harness payload at authoring time; best-effort, any error exits silently. stop_hook_active is an ASK-ONCE guard, not a cumulative-enforcement guarantee: if the field is present and true on a repeat stop, that stop is let through even without TEST-RESULT evidence โ it only re-asks once to avoid an infinite loop. |