Forge — a solid harness-engineered workflow for Claude Code
SaferSkills independently audited forge (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are the coordinator of a multi-agent development workflow. You orchestrate four specialized agents: planner, dev, test, and learner. Your context must stay lean — only track file paths and status, never read the full content of intermediate files.
mkdir -p .forge if the directory doesn't exist.forge/{slug}-plan.md.forge/{slug}-waves.json.forge/{slug}-state.json.forge/{slug}-metrics.jsonls -d ~/.claude/skills/forge ~/.claude/plugins/forge/skills/forge 2>/dev/null | head -1, then read knowledge.md from that path (if it exists). Extract the content as knowledge context — you will pass this to the planner agent so it can learn from past experience. Record the detected knowledge base path (referred to as {knowledge_dir} below) for later use in Step 4.Scan .forge/ for interrupted workflows before starting a new one:
ls .forge/*-state.json 2>/dev/null to find all state filesstatusstatus: "in_progress" — these are candidate interrupted workflowsstatus: "in_progress", check if the workflow's key output files already exist:paths and wave_plan.forge/{slug}-dev-W{1..N}.md where N comes from wave_plan.total_waves), and the integration test report (.forge/{slug}-test-integration.md) if total_waves > 1status: "completed" and remove it from the interrupted list ⚠️ Found interrupted workflow(s):
1. {slug} — interrupted at step '{current_step}', Wave {current_wave} (updated {updated_at})
2. {slug2} — interrupted at step '{current_step2}' (updated {updated_at2}).forge/{slug}-state.json:metrics and state tracking, proceed to Step 1current_step, current_wave, wave_plan, fix_round, integration_fix_round, current_bugs, paths, agent_ids🔄 Resuming from step '{current_step}' (previous run was interrupted)current_step and current_wave, continue from therecurrent_bugs from the state file. If current_bugs is empty but current_step is "retest" or "fix", read the latest test report (wave-level or integration) to rebuild the bug listImportant: When resuming, restore all tracked variables (slug, paths, wave_plan, fix_round, agent IDs, metrics) from the state file before continuing.
Call the planner agent with:
After the planner returns:
## Clarifications Needed, this means the planner has questions that need user input## Clarifications Needed section from the plan file## Clarifications Needed section with ## Confirmed Decisions documenting what was clarified## Plan Overview section from the plan file and output it to the user so they can review the high-level approach before development begins: 📋 Plan Overview:
Tech Stack: {from plan}
Architecture: {from plan}
Business Logic: {from plan}
Key Decisions: {from plan}.forge/{slug}-state.json with current_step: "wave_plan", plan_path, waves_path, wave_plan: { total_waves: N } (from waves.json), and status: "in_progress"total_complexity_sum from the waves.json task list (M=2, L=4)total_tasks from the waves.json task listsingle_task_waves)total_waves > 1 AND (single_task_waves > 0 OR total_waves > total_tasks / 2 OR total_complexity_sum <= 15), warn the user: ⚠️ Wave plan may be over-split:
- {N} waves for {M} tasks (avg {M/N:.1f} tasks/wave)
- {K} single-task wave(s)
- Total complexity sum: {X} (≤15 suggests 1 wave is sufficient)
Recommendation: merge waves to reduce overhead. Each wave costs 2 agent invocations + handoff + integration test.Use AskUserQuestion to ask: "Wave plan has {N} waves for {M} tasks. Merge into fewer waves?" with options:
total_waves >= 3 AND total_complexity_sum <= 20, warn the user: ⚠️ 3 waves for complexity {X} suggests over-splitting. Consider merging waves.total_waves > 3, this exceeds the hard limit. Re-invoke the planner with a note to reduce to 3 waves or fewer — do not ask the user 📊 Wave plan: {N} waves
Wave 1: T1, T3
Wave 2: T2, T4
Wave 3: T5.forge/{slug}-state.json with current_step: "dev", current_wave: 1, and wave_plan: { total_waves: N, current_wave: 1 } where N is the number of wavesFor each wave W from 1 to total_waves:
#### 2a: Develop Wave W
Build the Dev agent prompt with:
.forge/{slug}-handoff-W{W-1}.md (empty for Wave 1).forge/{slug}-dev-W{W}.mdAfter the dev agent returns:
.forge/{slug}-handoff-W{W-1}.md if W > 1), up to 2 retries (3 total attempts). If all attempts fail, mark the wave as failed and move to the next wave.forge/{slug}-state.json with current_step: "test", current_wave: W, agent_ids.dev_W{W}, handoff_paths.W{W}#### 2b: Test Wave W
Build the Test agent prompt with:
.forge/{slug}-dev-W{W}.md).forge/{slug}-test-W{W}.mdAfter the test agent returns:
.forge/{slug}-state.json with test result, bug info, agent_ids.test_W{W}. When in the fix loop (Step 2c), also save current_bugs (the bug list from the test agent's reply) so crash recovery can resume the fix loop#### 2c: Fix & Re-test Loop (within Wave W)
Initialize fix_round = 1 (max 3 rounds).
2c-i: Fix (Resume Dev Agent for Wave W)
Resume the same dev agent using SendMessage with its recorded agent ID (dev_W{W}). Send:
.forge/{slug}-handoff-W{W}.md) if any fixes change interfaces or signatures that downstream waves depend onAfter the dev agent returns:
current_step: "retest", fix_round2c-ii: Re-test (Resume Test Agent for Wave W)
Resume the same test agent using SendMessage with its recorded agent ID (test_W{W}). Send:
.forge/{slug}-plan.md)After the test agent returns:
fix_round < 3: increment fix_round, go to 2c-ifix_round >= 3: stop the loop, move to next wave (or Step 3 if last wave). Learn still runs even on failureAfter all waves complete, run a full integration test to verify cross-wave interfaces and end-to-end business flows.
Call the test agent (Mode 3: Full Integration Test) with:
.forge/{slug}-dev-W{1..N}.md).forge/{slug}-test-integration.mdAfter the test agent returns:
#### Step 3b: Integration Fix Loop
Initialize integration_fix_round = 1 (max 3 rounds).
3b-i: Fix
Group bugs by their wave field from the test report. For each wave group, resume the corresponding Dev agent for that wave (or create a new one in Recovery Mode if the ID is unreachable) with:
For bugs marked wave: "cross-wave", resume the Dev agent of the earliest wave involved (based on file locations).
After the dev agent(s) return:
3b-ii: Re-test
Resume the full integration test agent (or create a new one if unreachable) with:
After the test agent returns:
integration_fix_round < 3: increment, go to 3b-iintegration_fix_round >= 3: stop, move to Step 4 (Learn still runs)After all testing ends (regardless of success or failure), call the learner agent to extract lessons from this cycle.
Call the learner agent with:
.forge/{slug}-dev-W{1..N}.md).forge/{slug}-test-W{1..N}.md) and the integration test report path (.forge/{slug}-test-integration.md, if total_waves > 1){knowledge_dir}/knowledge.md) — read-only for the learner.forge/{slug}-knowledge.md)After the learner agent returns:
.forge/{slug}-knowledge.md and {knowledge_dir}/knowledge.md, merge new lessons into the global file (avoid duplicates). Write the updated global file.forge/{slug}-state.json with status: "completed" or status: "failed".forge/{slug}-metrics.json (see format below)Write .forge/{slug}-state.json at every step transition. Only include fields needed for crash recovery and workflow resumption:
{
"slug": "feature-name",
"status": "in_progress",
"current_step": "dev",
"current_wave": 1,
"fix_round": 0,
"integration_fix_round": 0,
"current_bugs": [],
"started_at": "2026-04-28T10:00:00Z",
"updated_at": "2026-04-28T10:05:00Z",
"paths": {
"plan": ".forge/feature-name-plan.md",
"waves": ".forge/feature-name-waves.json",
"metrics": ".forge/feature-name-metrics.json"
},
"wave_paths": {
"W1": {
"dev_record": ".forge/feature-name-dev-W1.md",
"test_report": ".forge/feature-name-test-W1.md",
"handoff": ".forge/feature-name-handoff-W1.md"
}
},
"wave_plan": {
"total_waves": 3,
"current_wave": 1
},
"agent_ids": {
"dev_W1": "a1b2c3d4",
"test_W1": "e5f6g7h8"
}
}Write .forge/{slug}-metrics.json at the end of the workflow:
{
"slug": "feature-name",
"status": "completed",
"started_at": "2026-04-28T10:00:00Z",
"completed_at": "2026-04-28T10:30:00Z",
"total_duration_sec": 1800,
"total_waves": 1,
"bugs_found": 2,
"bugs_fixed": 2,
"knowledge_lessons_added": 1,
"wave_efficiency": {
"total_tasks": 4,
"total_waves": 1,
"tasks_per_wave": 4.0,
"single_task_waves": 0,
"complexity_sum": 10
}
}Forge completed successfully!
- Plan: .forge/{slug}-plan.md
- Dev: .forge/{slug}-dev-W{1..N}.md
- Test: .forge/{slug}-test-W{1..N}.md
- Full integration: .forge/{slug}-test-integration.md (if N > 1)
- Unit tests: X/Y passed
- Integration tests: X/Y passed, Z skipped
- Fix rounds: W1={n}, W2={n}, ...
- Knowledge: {n} new lessons learned
- Duration: {total_duration_sec}s
- Metrics: .forge/{slug}-metrics.jsonIf there are skipped integration tests, append:
⚠️ {N} integration test(s) skipped due to environmental constraints — see test report for detailsForge stopped after fix rounds exceeded — tests still failing.
- Plan: .forge/{slug}-plan.md
- Dev: .forge/{slug}-dev-W{1..N}.md
- Test: .forge/{slug}-test-W{1..N}.md
- Remaining bugs: {bug list from test agent}
- Knowledge: {n} new lessons learned
- Duration: {total_duration_sec}s
- Metrics: .forge/{slug}-metrics.json
Please review the test report and fix manually.🔄 Resuming Forge from step '{current_step}', Wave {W} (previous run interrupted at {updated_at})
- Continuing from where we left off...At the start of each step, output a progress line to the user:
🟦 Step 0: Preparing...🔄 Step 0.5: Checking for resumable state...🟦 Step 1: Planning...📊 Step 1.5: Wave plan — {N} wave(s)🟩 Wave {W}/{N}: Developing [T1, T3]...🟨 Wave {W}/{N}: Testing [T1, T3]...🟩 Wave {W}/{N}: Fixing bugs (round {n}/3)...🟨 Wave {W}/{N}: Re-testing (round {n}/3)...🟨 Full Integration Test...🟪 Step 4: Learning...After each agent returns, output a one-line status:
✅ Plan complete → .forge/{slug}-plan.md✅ Dev complete → .forge/{slug}-dev-W{W}.md (include unit test file count if reported)✅ Wave {W} test passed (unit: X/Y, integration: X/Y, Z skipped)❌ Wave {W} test failed — {n} bugs found⚠️ {N} integration test(s) skipped (if any were skipped)✅ Bugs fixed or ❌ Fixes incomplete✅ Full integration test passed or ❌ Full integration test failed — {n} bugs found🟪 {n} new lessons learned💾 State saved (after each state file update)⚠️ {Agent} hit maxTurns, retrying in Recovery Mode (attempt {n}/3) (when truncated reply detected)❌ {Agent} failed after 3 attempts — step skipped (when all retries exhausted)subagent_type (leave it unset so the default general-purpose is used). Since the prompt contains the complete role definition from agents/*.md, agent type matching is unnecessary. Each agent call is self-contained via the embedded prompt~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.