Autonomous improvement loop for any codebase. Uses git worktrees to run every experiment in isolation — the main branch is never touched until a winning change is explicitly merged. Reads .claude/autoimprove/config.md for the measurement suite, then iterates: create worktree → propose → implement in worktree → measure → merge if improved, delete if not → log → repeat.
Scanned 5/27/2026
Install via CLI
openskills install benmarte/autoimprove---
description: Autonomous improvement loop for any codebase. Uses git worktrees to run every experiment in isolation — the main branch is never touched until a winning change is explicitly merged. Reads .claude/autoimprove/config.md for the measurement suite, then iterates: create worktree → propose → implement in worktree → measure → merge if improved, delete if not → log → repeat.
---
# 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
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
1. Check `.claude/autoimprove/config.md` exists. If not, stop: "Run /autoimprove:setup first."
2. Check git is available: `git status`
3. Confirm main working tree is clean. If not, stop: "Please commit or stash changes before running autoimprove."
4. Record the base commit: `git rev-parse HEAD` — all experiments branch from here.
5. Run the worktree skill's **setup** step to create `.claude/autoimprove/worktrees/` and update `.gitignore`.
6. Run the measure skill in the **main directory** to get the BASELINE score.
7. 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 1
- **`total_iterations`** — Use this as the display total (e.g., "Iteration 5/10")
- **`session_mode`** — If `continue`, skip creating a new session header; instead update the existing one:
- Update `**Planned:**` to the new total if it changed
- Update `**Status:**` to `IN_PROGRESS`
- **`baseline_score`** — If provided, skip baseline measurement and use this value
- **`experiment_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:
```bash
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):
```bash
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:
```bash
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:
```bash
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:
```bash
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:
1. Read `.claude/autoimprove/log.md`
2. Find the last line matching `**Status:** IN_PROGRESS`
3. Replace it with `**Status:** IN_PROGRESS (N/M completed)` where N is the current iteration number and M is the total planned
4. 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:
1. Read `.claude/autoimprove/log.md`
2. Find the last `**Status:** IN_PROGRESS` line
3. Replace with `**Status:** COMPLETED (N/N)`
4. Write the file back
```bash
# 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
No comments yet. Be the first to comment!