AutoImprove Loop Skill
Every experiment runs in an isolated git worktree. The main codebase is never modified during experiments. Only winning changes get squash-merged back.
Main branch ──────────────────────────────────── (never touched mid-session)
│ │
experiment-001 experiment-002
(kept ✅ → merge) (discarded ❌ → deleted)
Pre-flight checks
Before the first iteration, print each check as you run it:
━━━ Pre-flight ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✓ Config found
✓ Git working tree clean
✓ Base commit: abc1234
✓ Worktree directory ready
✓ Baseline score: XX/100
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- Check
.claude/autoimprove/config.mdexists. If not, stop: "Run /autoimprove:setup first." - Check git is available:
git status - Confirm main working tree is clean. If not, stop: "Please commit or stash changes before running autoimprove."
- Record the base commit:
git rev-parse HEAD— all experiments branch from here. - Run the worktree skill's setup step to create
.claude/autoimprove/worktrees/and update.gitignore. - Run the measure skill in the main directory to get the BASELINE score.
- Report: "Baseline: XX/100. All experiments will run in isolated worktrees. Main branch is safe."
Session Header
After pre-flight passes, write a session header to .claude/autoimprove/log.md:
## Session — [ISO 8601 timestamp]
**Planned:** N iterations
**Focus:** "focus string" (or "all improvement areas" if none)
**Baseline:** XX/100
**Base commit:** [full SHA]
**Status:** IN_PROGRESS (0/N completed)
If the log file doesn't exist, create it with the project header first:
# .claude/autoimprove/log.md
> Generated by [autoimprove](https://github.com/benmarte/autoimprove) — Claude Code Plugin
> Project: **[project name]** · Stack: [detected stack] · Started: [date]
---
Then append the session header.
Continue Mode
When invoked with continue-mode parameters (from the /autoimprove:continue command), the loop behavior changes:
start_iteration— Start numbering from this value instead of 1total_iterations— Use this as the display total (e.g., "Iteration 5/10")session_mode— Ifcontinue, skip creating a new session header; instead update the existing one:- Update
**Planned:**to the new total if it changed - Update
**Status:**toIN_PROGRESS
- Update
baseline_score— If provided, skip baseline measurement and use this valueexperiment_offset— Start experiment numbering from this value to avoid branch name collisions
In continue mode, the pre-flight still runs (clean tree, config check, worktree setup) but skips creating a new session header and optionally skips baseline measurement.
Progress Updates
CRITICAL: At the start of every step, you MUST output a visible progress line to the user. Do not silently run tools — always print status first. Use this format:
━━━ Iteration N/TOTAL ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔬 STEP_NAME: brief description of what's happening
Example progress lines:
━━━ Iteration 1/5 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔬 PROPOSE: Targeting error handling in src/api/client.ts
🔬 SNAPSHOT: Measuring BEFORE score...
🔬 IMPLEMENT: Adding try/catch to unhandled async calls
🔬 MEASURE: Measuring AFTER score...
🔬 DECIDE: 85 → 89 (+4 pts) — KEPT ✅
🔬 LOG: Recorded to .claude/autoimprove/log.md
Never run more than one step without printing a progress line. The user must always know what iteration you're on and what phase you're in.
The Loop
Step 1 — CREATE WORKTREE
Use the worktree skill to create a new isolated branch and directory:
EXPERIMENT_ID=$(printf "%03d" $N)
git worktree add -b "autoimprove/experiment-$EXPERIMENT_ID" \
".claude/autoimprove/worktrees/experiment-$EXPERIMENT_ID"
All work for this iteration happens inside .claude/autoimprove/worktrees/experiment-$EXPERIMENT_ID/.
The main directory is not touched.
Step 2 — PROPOSE
If a FOCUS string was provided: Every iteration targets that specific focus. Break the focus into file-by-file or function-by-function sub-tasks and tackle one per iteration. Do not rotate to other areas — stay on the focus until all iterations are used or the focus is fully addressed.
If no FOCUS was provided: Choose one focused improvement from the Improvement Areas in .claude/autoimprove/config.md. Rotate areas — don't repeat an area that failed last time.
State the hypothesis explicitly:
"I will [specific change] in [file(s)] because I expect [metric] to improve by ~[X] points."
Step 3 — SNAPSHOT (BEFORE score)
Measure from inside the worktree directory (same commands, different cwd):
cd .claude/autoimprove/worktrees/experiment-$EXPERIMENT_ID
# run measurement suite from .claude/autoimprove/config.md
Record as BEFORE.
Step 4 — IMPLEMENT
Make the change inside the worktree. The main directory is untouched. Commit the change to the experiment branch:
cd .claude/autoimprove/worktrees/experiment-$EXPERIMENT_ID
git add -A
git commit -m "experiment($EXPERIMENT_ID): $HYPOTHESIS_ONE_LINE"
Step 5 — MEASURE (AFTER score)
Run the full measurement suite again from inside the worktree. Record as AFTER.
Step 6 — DECIDE
If AFTER > BEFORE — KEEP ✅
Squash-merge the experiment back to main:
cd [main project root]
git merge --squash "autoimprove/experiment-$EXPERIMENT_ID"
git commit -m "autoimprove($EXPERIMENT_ID): $HYPOTHESIS_ONE_LINE
Score: $BEFORE → $AFTER (+$DELTA pts)
Files changed: $FILES"
# Clean up
git worktree remove ".claude/autoimprove/worktrees/experiment-$EXPERIMENT_ID"
git branch -D "autoimprove/experiment-$EXPERIMENT_ID"
If AFTER == BEFORE — KEEP ✅ only for clear readability wins, DISCARD otherwise
Same merge process as above if keeping, discard process if not.
If AFTER < BEFORE — DISCARD ❌
Main branch is already untouched. Just delete the worktree:
git worktree remove ".claude/autoimprove/worktrees/experiment-$EXPERIMENT_ID" --force
git branch -D "autoimprove/experiment-$EXPERIMENT_ID"
No rollback needed — there was nothing to roll back.
Step 7 — LOG
Append to .claude/autoimprove/log.md in the main directory:
## Iteration N — [timestamp]
**Hypothesis:** [what you tried and why]
**Branch:** autoimprove/experiment-NNN
**Files changed:** [list]
**Before:** [X/100] — type: X, build: X, tests: X, lint: X
**After:** [X/100] — type: X, build: X, tests: X, lint: X
**Decision:** KEPT ✅ (merged to main) / DISCARDED ❌ (worktree deleted)
**Reason:** [one sentence]
Step 7b — UPDATE SESSION STATUS
After logging the iteration, update the session header's **Status:** line:
- Read
.claude/autoimprove/log.md - Find the last line matching
**Status:** IN_PROGRESS - Replace it with
**Status:** IN_PROGRESS (N/M completed)where N is the current iteration number and M is the total planned - Write the file back
If the status line cannot be found, append a warning to the log and continue — the iteration records are the source of truth.
Step 8 — REPEAT from Step 1
Session end — cleanup
After all iterations (or if the user stops early):
Update the session header status to completed:
- Read
.claude/autoimprove/log.md - Find the last
**Status:** IN_PROGRESSline - Replace with
**Status:** COMPLETED (N/N) - Write the file back
# Remove any remaining experiment worktrees
for wt in .claude/autoimprove/worktrees/experiment-*; do
git worktree remove "$wt" --force 2>/dev/null
done
git branch | grep "autoimprove/experiment" | xargs git branch -D 2>/dev/null
rm -rf .claude/autoimprove/worktrees
Print a final summary table:
━━━ Session Complete ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 Score: BASELINE → FINAL (+/- DELTA)
🔁 Iterations: N total — X kept ✅, Y discarded ❌
📝 Merged commits:
• abc1234 autoimprove(001): description
• def5678 autoimprove(003): description
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Universal Improvement Areas
Rotate through these (add language-specific ones from .claude/autoimprove/config.md):
- Type safety — fix type errors, replace
any/interface{}/untyped constructs - Error handling — unhandled promises, bare
catch {}, swallowed errors - Dead code — unused imports, variables, unreachable branches
- Code duplication — extract repeated logic (3+ occurrences) into shared utilities
- Naming & readability — cryptic names, functions over ~50 lines
- Performance — N+1 query patterns, missing memoization, unnecessary allocations
- Security — hardcoded secrets, missing input validation, unguarded auth routes
- Tests — add a test for the most critical untested function, fix flaky tests
Safety Rules
- Main branch is never modified until a winning experiment is explicitly squash-merged
- Never modify lock files, generated files, migrations,
.env— in any worktree - Never run deploy, publish, or push commands
- If the same area fails 3 iterations in a row, skip it and note in the log
- After 10 iterations, pause, clean up worktrees, and wait for human review
- On any unexpected error: run the worktree skill's cleanup step, then stop and report