Start or resume an agentic loop to implement a feature until verification passes
Implements a feature using a persistent agentic loop that continues until all verification commands (build, tests, lint, typecheck) pass. Use this when you need reliable, test-driven feature implementation that automatically retries with different approaches on failures.
/plugin marketplace add panayiotism/claude-harness/plugin install claude-harness@claude-harnessImplement a feature using a persistent agentic loop that continues until verification passes:
Arguments: $ARGUMENTS
"Claude marked features complete without proper testing" - NEVER trust self-assessment. Always run actual verification commands.
Check for existing loop state:
.claude-harness/loop-state.jsonstatus is "in_progress" and matches $ARGUMENTS:
Read feature definition:
.claude-harness/feature-list.jsonverificationCommandsverificationCommands is missing, detect or ask userInitialize/update .claude-harness/loop-state.json:
{
"version": 1,
"feature": "{feature-id}",
"featureName": "{feature name}",
"status": "in_progress",
"attempt": 1,
"maxAttempts": 10,
"startedAt": "{timestamp}",
"lastAttemptAt": null,
"verification": {
"build": "npm run build",
"tests": "npm run test",
"lint": "npm run lint",
"typecheck": "npx tsc --noEmit",
"custom": []
},
"history": [],
"lastCheckpoint": null,
"escalationRequested": false
}
Before attempting any work, verify the environment is healthy:
git stash or inform userReport health status:
┌─────────────────────────────────────────────────────────────────┐
│ AGENTIC LOOP: {feature-name} │
├─────────────────────────────────────────────────────────────────┤
│ Health Check: ✅ PASSED (build succeeds, tests baseline) │
│ Attempt: {n}/{maxAttempts} │
│ Previous attempts: {count} │
└─────────────────────────────────────────────────────────────────┘
Read attempt history to understand what was tried:
Plan the current attempt:
Execute the implementation:
Update loop state after attempt:
{
"history": [..., {
"attempt": {n},
"timestamp": "{ISO timestamp}",
"approach": "{description of what was tried}",
"filesModified": ["{paths}"],
"filesCreated": ["{paths}"],
"result": "pending_verification"
}]
}
Run ALL verification commands:
┌─────────────────────────────────────────────────────────────────┐
│ VERIFICATION PHASE │
├─────────────────────────────────────────────────────────────────┤
│ ⏳ Running: npm run build │
│ ⏳ Running: npm run test │
│ ⏳ Running: npm run lint │
│ ⏳ Running: npx tsc --noEmit │
└─────────────────────────────────────────────────────────────────┘
Collect verification results:
Determine overall result:
Celebration and checkpoint:
┌─────────────────────────────────────────────────────────────────┐
│ ✅ VERIFICATION PASSED │
├─────────────────────────────────────────────────────────────────┤
│ Build: ✅ PASSED │
│ Tests: ✅ PASSED │
│ Lint: ✅ PASSED │
│ Typecheck: ✅ PASSED │
├─────────────────────────────────────────────────────────────────┤
│ Feature complete in {n} attempts! │
└─────────────────────────────────────────────────────────────────┘
Create git checkpoint:
git add -Afeat({feature-id}): {feature-name}
Implemented via agentic loop ({n} attempts)
Verification passed:
- Build: ✅
- Tests: ✅
- Lint: ✅
- Typecheck: ✅
Update loop state to completed:
{
"status": "completed",
"completedAt": "{timestamp}",
"totalAttempts": {n},
"finalCommit": "{commit-hash}",
"history": [..., {
"attempt": {n},
"result": "passed",
"verificationResults": {
"build": "passed",
"tests": "passed",
"lint": "passed",
"typecheck": "passed"
}
}]
}
Update feature-list.json:
passes: trueReport success and next steps:
/claude-harness:checkpoint to push and create PRAnalyze failures:
┌─────────────────────────────────────────────────────────────────┐
│ ❌ VERIFICATION FAILED │
├─────────────────────────────────────────────────────────────────┤
│ Build: ✅ PASSED │
│ Tests: ❌ FAILED - 2 tests failing │
│ Lint: ✅ PASSED │
│ Typecheck: ❌ FAILED - 3 type errors │
├─────────────────────────────────────────────────────────────────┤
│ Attempt {n}/{maxAttempts} │
└─────────────────────────────────────────────────────────────────┘
Parse and categorize errors:
Update loop state with failure details:
{
"history": [..., {
"attempt": {n},
"result": "failed",
"errors": [
"TS2322: Type 'string' is not assignable to type 'number' at src/auth.ts:42",
"Test: auth.test.ts - expected 200, got 401"
],
"verificationResults": {
"build": "passed",
"tests": "failed",
"lint": "passed",
"typecheck": "failed"
}
}]
}
Check attempt count:
attempt < maxAttempts: Continue to Phase 5 (Retry)attempt >= maxAttempts: Go to Phase 6 (Escalation)Increment attempt counter and save state:
{
"attempt": {n+1},
"lastAttemptAt": "{timestamp}"
}
Analyze what went wrong:
Plan new approach:
Return to Phase 2 (Attempt Implementation)
If max attempts reached without success:
┌─────────────────────────────────────────────────────────────────┐
│ ⚠️ ESCALATION REQUIRED │
├─────────────────────────────────────────────────────────────────┤
│ Max attempts ({maxAttempts}) reached without success │
│ │
│ Attempts Summary: │
│ 1. {approach} → {error summary} │
│ 2. {approach} → {error summary} │
│ ... │
│ │
│ Recurring Issues: │
│ - {pattern of failures} │
│ │
│ Recommendation: │
│ {suggested human intervention or alternative approach} │
└─────────────────────────────────────────────────────────────────┘
Update loop state:
{
"status": "escalated",
"escalationRequested": true,
"escalationReason": "{summary of why automation couldn't complete}",
"escalatedAt": "{timestamp}"
}
Offer options:
/claude-harness:implement {feature-id} --max-attempts 20If context window runs out during a loop:
Loop state is preserved in .claude-harness/loop-state.json
SessionStart hook will display:
┌─────────────────────────────────────────────────────────────────┐
│ 🔄 ACTIVE LOOP: {feature-id} (attempt {n}/{max}) │
│ Last: "{approach summary}" → {result} │
│ Resume: /claude-harness:implement {feature-id} │
└─────────────────────────────────────────────────────────────────┘
Running /claude-harness:implement {feature-id} resumes from Phase 0
/claude-harness:implement {feature-id}.claude-harness/loop-state.jsonstatus: "aborted" in loop-state.json/claude-harness:implement {feature-id} --max-attempts {n}