From easy-cheese
Fans out an approved spec into 5+ parallel implementation PRs with per-curd workers, a wiring phase, and post-merge review. Use when the user mentions a spec and says to parallelize, fan out, or 'send through the factory'.
How this skill is triggered — by the user, by Claude, or both
Slash command
/easy-cheese:cheese-factoryThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Use this skill when an approved spec decomposes into 5+ file-disjoint behavioural curds and the user wants the whole implementation parallelised, reviewed per-curd, integrated, reviewed again at the seam, and shipped as 1–N reviewable PRs.
Use this skill when an approved spec decomposes into 5+ file-disjoint behavioural curds and the user wants the whole implementation parallelised, reviewed per-curd, integrated, reviewed again at the seam, and shipped as 1–N reviewable PRs.
Do not use it for single coherent feature work (/cook or /ultracook), fuzzy planning (/mold), review-only work (/age), or specs that decompose into fewer than 5 curds (/ultracook).
/cheese-factory is the portable, harness-agnostic sibling of /fromagerie. Same decomposition pattern, same dual fan-out/fan-in, no bespoke agent files. Every sub-agent is a general-purpose full-peer worker driven by an in-prompt skill invocation.
Accept:
/cheese-factory <spec-path-or-slug> [--hard] [--resume <slug>]
SPEC=$(python3 ${CLAUDE_SKILL_DIR}/scripts/cheese-factory.pyz artifact-path specs <slug>), then read "$SPEC". The resolver anchors specs at the per-project durable corpus (see shared/formatting.md § Corpus location).--hard — propagate the /hard-cheese metacognitive gate flag through per-curd /cook --hard --auto and the Phase 6 /cure --hard --auto --stake medium+. The orchestrator does not fire the gate itself. See skills/hard-cheese/SKILL.md.--resume <slug> — read .cheese/cheese-factory/<slug>/manifest.yaml, find the latest phase marked complete, and continue from the next phase./cheese-factory does not accept fuzzy or open-ended asks — route those to /mold first. The orchestrator assumes the contract is locked.
--auto is implicit. After Phase 0 gate approval, the chain runs autonomously with no per-step handoff questions. There is no interactive mode — the value of this skill is unattended parallel execution.
/cheese-factory vs alternatives| Skill | Use when |
|---|---|
/cook | Single unambiguous task, no decomposition. |
/ultracook | Single coherent spec, high-blast-radius, sequential review pipeline. |
/cheese-factory | Spec decomposes into 5+ file-disjoint behavioural curds. |
/fromagerie | Same problem on Anthropic Claude Code with the bespoke agent files installed and a preference for specialised agent contracts. |
In cheese-factory terms, a curd is the smallest commit-worthy unit of behaviour: small enough to be worked independently, but intended to be pressed back into the whole feature.
The Phase 0 decomposer produces three artifact lists from the spec:
seed[] — foundational types / interfaces / enums that 2+ curds depend on.curds[] — parallel units of behaviour, file-disjoint, one acceptance criterion each.wiring[] — integration tasks with topological dependencies (barrels, registrations, routes, config).Every curd must satisfy all five. Token budgets are explicitly not a criterion — LLM agents cannot estimate their own token usage reliably, and the five behavioural criteria substitute. Curds remain bounded by their file scope, which is decomposer-controlled.
| # | Criterion | Decomposer check |
|---|---|---|
| 1 | One behaviour per curd | Describable in a single declarative sentence ("adds X", "extracts Y", "renames Z", "fixes A"). If the description needs "and" between two distinct behaviours, split. |
| 2 | One acceptance criterion | Maps to exactly one bullet in the spec's Acceptance Criteria / User Story list. Curds collectively cover every acceptance criterion 1:1. |
| 3 | One test target | A single focused test command verifies this curd alone (e.g., vitest run src/orders/order.test.ts). If the curd needs N test commands, it's N curds. |
| 4 | File-disjoint | No two curds list the same file. HARD CONSTRAINT. |
| 5 | Commit-worthy alone | After this curd's commit, just check (or project equivalent) passes without sibling curds merged. Implied by 4 plus seed carrying any shared deps. |
If criterion 4 cannot be satisfied because two curds genuinely share a file, the shared content belongs in seed (if foundational) or wiring (if integration). Curds never share files.
The per-run manifest is written as YAML at .cheese/cheese-factory/<slug>/manifest.yaml.
YAML is the human/agent-facing syntax; the contract stays schema-shaped and is
documented in references/manifest-schema.json. Keep manifests in the JSON-compatible
subset of YAML: mappings, lists, strings, numbers, booleans, and nulls only; no anchors,
aliases, tags, or multi-document streams.
The PR plan follows the same convention — written as YAML at
.cheese/cheese-factory/<slug>/pr-plan.yaml, with its shape documented in
references/pr-plan-schema.json. ${CLAUDE_SKILL_DIR}/scripts/cheese-factory.pyz pr_plan_to_branches reads either YAML
or JSON for backward compatibility, but YAML is the canonical format.
The decomposer's output is validated by ${CLAUDE_SKILL_DIR}/scripts/cheese-factory.pyz validate_manifest for required
sections and field shapes, then by ${CLAUDE_SKILL_DIR}/scripts/cheese-factory.pyz validate_decomposition against:
If validation fails: re-run decomposer with violations highlighted. Max 2 retries before escalating to the user.
Eight phases. The orchestrator walks them top-to-bottom and stops after the last entry or any halt.
| # | Phase | Shape |
|---|---|---|
| 0 | Pre-compile | Read spec, decompose via heavy general-purpose sub-agent, validate against the five criteria, user gate |
| 1 | Seed | Orchestrator inline edits via /cheez-write (or host edit tool if tilth MCP is unavailable), commit, push |
| 2 | Curds (fan-out) | N parallel general-purpose spawns; each runs /cook --auto → /press --auto → /age --auto (inline-degrade) → /cure --auto --stake medium+ and commits |
| 3 | Merge curds (fan-in) | Cherry-pick curd commits → orchestrator branch; /melt on conflicts |
| 4 | Wiring (sequential within wave) | Integration files only; per-task general-purpose spawn with wiring-only prompt |
| 5 | Final merge wiring | Wiring commits → orchestrator branch; conflicts here = halt (decomposer error) |
| 6 | Post-merge review (fresh-context, ultracook-style) | Three sub-agent spawns: /press --auto, /age --auto, /cure --auto --stake medium+. Single pass. |
| 7 | PR plan + publish | Heavy PR planner sub-agent decides layout, orchestrator delegates publish via skill discovery (/pr-stack, /gh, fallbacks) |
Read the spec from the argument (or, if --resume <slug>, read the manifest and skip to the next incomplete phase).
Validate the spec has: Executive Summary, Problem Statement, User Stories, Acceptance Criteria, Quality Gates. Fail fast if any is missing.
Hard worktree gate: detect the host's worktree mechanism (Conductor, git worktrees, plain branches) and prompt if working on the default branch. Never skipped.
Spawn a heavy general-purpose decomposer sub-agent (prompt template at references/decomposer-prompt.md) with the spec text, the five criteria, the validation checks, and instructions to produce seed[], curds[], wiring[], and a manifest scaffold.
The decomposer may invoke /culture or /briesearch internally if it needs to ground its decomposition against the codebase or external docs.
Front-load permissions: present the per-host permission manifest (git, the project's quality gate command, the host-specific spawn primitive) to the user. On approval, merge into the host's settings.
Present the full plan:
## Cheese-Factory Plan: <slug>
### Seed (sequential)
1. <description> — files: [<list>]
### Curds (parallel)
| # | Behaviour | Acceptance criterion | Files | Test target |
|---|---|---|---|---|
### Wiring DAG
| # | Type | File | Depends on |
|---|---|---|---|
### Review Pipeline
Per-curd: /cook → /press → /age (inline-degrade) → /cure
Post-merge: /press → /age → /cure (fresh-context sub-agents)
A. Approve — start execution
B. Modify — change the decomposition
C. Re-decompose — different boundaries
D. Pause — hold off
Use the shared handoff gate in ../../shared/handoff-gate.md for this approval step. All four options keep cheese-factory running internally (no skill transition) — they use continue: identifiers rather than dispatch: commands per the gate vocabulary:
continue: write-manifest-then-seed: write .cheese/cheese-factory/<slug>/manifest.yaml, set phase: gate_approved, then proceed with Phase 1 (seed execution).continue: ask-for-decomposition-change: ask one targeted question for the requested decomposition change, then re-render the plan.continue: re-run-decomposer: re-run the decomposer with the user's boundary instruction. Retry at most twice.dispatch: none: leave the manifest draft and report its path.Do NOT proceed without explicit approval.
Drop: full spec text, permission manifest, decomposition reasoning. Keep: slug, spec summary (≤2K chars), manifest path, quality gate commands.
Seed items are minimal — only the shared types / protocols that curds cannot compile without. The orchestrator executes seed inline (a deliberate exception to the orchestrator's "never write code" rule because seed is always small).
For each seed item:
/cheez-write when tilth MCP is present; otherwise fall back to the host's native edit tool (per the cheez-* portability rule in README.md). The skill must not hard-fail when /cheez-write is unavailable.just check or equivalent) — if gates fail, STOP./commit (if available) or git commit direct.Push to branch — curds branch from HEAD.
Update manifest: phase: seed_complete, commit SHAs.
Spawn ALL curd workers in a single message via the host's fan-out primitive. If more than 5 curds, dispatch in waves of 5.
Each curd worker is a general-purpose sub-agent (full peer of the orchestrator — same model, full tools, full skills, full MCP) given the per-curd prompt at references/curd-prompt.md.
Collect results as curds complete. For failed curds: retry ONCE with error context. Mark retry_count: 1; do not retry twice.
Update manifest: curd statuses, worktree paths, branch names, commit SHAs.
Drop: decomposer artifacts, curd dispatch prompts, curd return summaries. Keep: slug, manifest path, quality gate commands, curd branch list. Read from disk when needed: wiring DAG.
Cherry-pick curd commits onto the orchestrator branch in curd-id order:
For each curd (in order):
git cherry-pick <curd_commit_sha> — or, if the host fan-out used worktrees, merge the worktree branch./melt if available, else fall back to mergiraf → git rerere → manual./melt cannot resolve: STOP, fall back to per-curd PRs in Phase 7.After all curds merged: run quality gates. If failing, STOP and report — curds passed individually but conflict in aggregate (decomposer error).
Read wiring DAG from manifest. Dispatch wiring tasks in topological order, sequentially within each wave (concurrent commits to the same working directory race on git's index.lock).
Each wiring worker is a general-purpose sub-agent with the prompt template at references/wiring-prompt.md.
For failed wiring tasks: retry ONCE. If still failing, mark incomplete in manifest.
Cherry-pick wiring commits onto the orchestrator branch.
If conflicts arise here: STOP. Wiring conflicts mean the decomposer's DAG was wrong (wiring touched implementation territory, or two wiring tasks shared a file outside the DAG). Do not auto-resolve.
Drop: wiring DAG details, per-curd diffs, intermediate merger reports. Keep: slug, spec path (for downstream skills), quality gates, list of all changed files, list of all commit SHAs (curds + seed + wiring).
By Phase 6 the orchestrator's context is heavy. Run the final review pipeline in fresh-context sub-agents to keep review reasoning adversarial and clean.
Three sequential spawns:
/press --auto on the merged diff — writes .cheese/press/<slug>.md./age --auto on the merged diff — writes .cheese/age/<slug>.md./cure --auto --stake medium+ on the age findings — writes .cheese/cure/<slug>.md.Each spawn is a full-peer general-purpose sub-agent. Pass the no-chain-forward directive (same as /ultracook) so each spawn runs its phase only.
Single pass through — no two-cure-pass cap. Curds each had their own press/age/cure; this is integration-level review.
If any phase writes status: halt: <reason> in its slug, surface the halt and STOP. If /cure writes next: done, continue to Phase 7.
Spawn a heavy general-purpose PR planner sub-agent (prompt template at references/pr-planner-prompt.md) with the wiring DAG, the manifest, the merged diff, and the spec summary.
The planner emits one of four shapes:
| Shape | When | PR layout |
|---|---|---|
single | Small total diff, tightly coupled | All commits in one PR. |
orthogonal_flat | Curds touch disjoint slices, no seed/wiring coupling | N PRs each branching from main. |
stacked_linear | Linear dependencies seed → curds → wiring | gt/gh stack. |
diamond_stack | Seed and wiring exist; curds independent of each other | seed PR (base) → N parallel curd PRs → wiring PR. |
The planner writes its grouping to .cheese/cheese-factory/<slug>/pr-plan.yaml and returns control.
Before publishing PRs, the orchestrator detects which skills are available and picks the right delegate:
| Need | Prefer | Fallback |
|---|---|---|
| Stack publish | /pr-stack (Graphite gt or gh stack) | manual gh pr create --base <prev-branch> chain |
| Commits | /commit | git commit direct |
| PR publish | /gh | gh pr create direct |
| Merge conflicts | /melt | mergiraf → rerere → kdiff3 direct |
Detection: attempt to invoke the skill via the host's Skill tool; on unrecognised-skill error, fall back. Cache the result for the rest of the phase.
For each PR group in the plan:
pr-plan.yaml.${CLAUDE_SKILL_DIR}/scripts/cheese-factory.pyz pr_plan_to_branches to convert pr-plan.yaml to branch-creation commands)./gh if available, else gh pr create direct)./pr-stack with the ordered branch list.## Cheese-Factory Complete: <slug>
### Results
| Phase | Status | Detail |
|---|---|---|
| Seed | complete | 2 commits |
| Curds | 5/6 succeeded | Curd #4 failed after retry |
| Merge | complete | — |
| Wiring | 4/4 complete | — |
| Final merge | complete | — |
| Post-merge review | press: pass, age: 3 findings, cure: 3 applied |
| PR plan | diamond_stack | seed + 5 curds + wiring = 7 PRs |
### PRs
| PR | Title | Stack base |
|---|---|---|
| #101 | feat(orders): shared types | main |
| #102 | feat(orders): order entity | #101 |
| ... |
### Manual actions needed
- Curd #4 failed: {error_summary}
Manifest: .cheese/cheese-factory/<slug>/manifest.yaml
The orchestrator reads ONE thing: the spec. Everything else is delegated.
Must not:
Should:
status and next fields, never on sub-agent stdout.Three seams where the orchestrator drops accumulated context.
| Seam | After | DROP | KEEP |
|---|---|---|---|
| C1 | Phase 0 (gate approved) | Full spec text, permission manifest, decomposition reasoning | Slug, spec summary (≤2K), manifest path, quality gates |
| C2 | Phase 2 (curds done) | Decomposer artifacts, curd dispatch prompts, curd return summaries | Slug, manifest path, quality gates, curd branch list |
| C3 | Phase 5 (final merge done) | Wiring DAG, per-curd diffs, merger details | Slug, spec path, quality gates, changed files list, all commit SHAs |
At each seam, write a self-summary to the manifest before dropping:
{
"phase_summary": "<2-3 sentences: what happened, what succeeded/failed, what's next>",
"carry_forward": ["slug", "spec_summary", "manifest_path", "quality_gates"]
}
On --resume, read phase_summary from the manifest. This is the only cross-seam continuity mechanism — do not rely on conversation history.
The orchestrator never names a specific host primitive. Any primitive that satisfies all five invariants below is acceptable. See references/spawn-primitive-reference.md for host-by-host examples.
.cheese/<phase>/<slug>.md per the schema. The orchestrator decides chain progression from the slug, never from stdout.If the host harness exposes no fan-out primitive at all, /cheese-factory is the wrong skill — recommend /ultracook for the same review semantics in the parent's own context.
Every phase writes a handoff slug to .cheese/<phase>/<slug>.md (or, for per-curd workers, to .cheese/cheese-factory/<slug>/curds/<curd-id>.md) with the minimum shape:
status: ok | halt: <one-line reason>
next: <phase-name | done>
artifact: <path-to-richer-report-if-any>
<one-line orientation: what this phase did>
For phases that already write rich reports (/age, /press, /cure), the schema is prepended at the top of the same file.
/cheese-factory runs the project's quality gate command (typically just check per AGENTS.md) at four points:
/cure step)./cure.If any gate fails: STOP, report, do not silently fix.
--hard propagation/cheese-factory <spec> --hard:
--hard to per-curd /cook --hard --auto — each curd gets its own hard-cheese vibecheck at its /cure share-for-review boundary.--hard to Phase 6 /cure --hard --auto --stake medium+ — the integration /cure runs the share-for-review vibecheck too.The orchestrator does not invoke /hard-cheese itself — it propagates the flag. See skills/hard-cheese/SKILL.md.
--resume <slug>Read manifest at .cheese/cheese-factory/<slug>/manifest.yaml, find the latest phase marked complete, skip to the next phase. Report: Resuming <slug> from phase <N>.
If the manifest references commits that no longer exist (rebased, deleted), fail fast and report — do not silently re-execute the phase.
| Failure | Recovery |
|---|---|
| No spec argument | STOP. Report cheese-factory requires an approved spec; run /mold first if you need to shape one. Do not auto-dispatch — cross-skill handoffs stay user-visible. |
| Overlap / criterion violation in decomposer output | Re-run decomposer (max 2 retries) |
| Seed gate failure | STOP, report — do not dispatch curds |
| Curd fails | Retry once with error context, then mark failed |
| All curds fail | STOP, no merge/wiring |
| Curd merge conflict | /melt; if /melt fails, fall back to per-curd PRs |
| Wiring agent fails | Retry once, mark incomplete if still failing |
| Phase 5 conflicts | STOP — decomposer error, report to user |
Phase 6 /press or /age halt | Surface halt, STOP |
Phase 6 /cure cannot apply any finding | Surface report, STOP |
/pr-stack not available, plan calls for stack | Fall back to manual gh pr create --base chain |
--resume on missing manifest | Fail fast |
Never proceed past Phase 0 gate without explicit user approval. Never claim green on partial work.
/age nesting depth: curd workers invoke /age which normally fans out to 6 review sub-agents (level 2, blocked). /cheese-factory requires /age to support an inline-degrade mode for sub-agent invocation — see skills/age/SKILL.md "Inline-degrade mode".git index.lock races even when files differ.git push or gh pr create without explicit Bash allowlist. The orchestrator must handle all push / PR operations./worktree-sweep (or host equivalent) after the pipeline completes.references/decomposer-prompt.md — heavy decomposer sub-agent prompt template.references/curd-prompt.md — per-curd worker prompt template.references/wiring-prompt.md — per-wiring task prompt template.references/pr-planner-prompt.md — PR planner sub-agent prompt template.references/manifest-schema.json — JSON Schema for the manifest.references/pr-plan-schema.json — JSON Schema for the PR plan, $ref'd from manifest-schema.json.references/spawn-primitive-reference.md — host-by-host invocation examples plus the five invariants.${CLAUDE_SKILL_DIR}/scripts/cheese-factory.pyz validate_manifest — Phase 0 structural validation of required manifest sections and fields.${CLAUDE_SKILL_DIR}/scripts/cheese-factory.pyz validate_decomposition — Phase 0 semantic validation of decomposer output against the five criteria.${CLAUDE_SKILL_DIR}/scripts/cheese-factory.pyz validate_pr_plan — Phase 7 validation of PR planner output before branch creation.${CLAUDE_SKILL_DIR}/scripts/cheese-factory.pyz pr_plan_to_branches — converts pr-plan.yaml to branch-creation commands for Phase 7.subagent_type, do not restrict tools or MCP access.--resume)./gh directly without confirming via the user-approved permission manifest from Phase 0.skills/age/references/voice.md in this repo): lead the final report with what happened, flag residual risk as certain | speculating | don't know, do not manufacture follow-ups.npx claudepluginhub paulnsorensen/easy-cheeseDecomposes specs/PRDs/plans into independent tasks, assigns to builder agents for parallel execution in waves respecting dependencies, then integrates results. For fast multi-file feature implementation.
Decomposes large tasks (migrations, multi-issue fixes, big features) into parallel work packages with quality gates. Useful for reducing PR cycle time and avoiding merge conflicts.
Orchestrates a full build pipeline from PRD: plans tasks, implements in parallel, and reviews results. Routes simple work to a lighter workflow.