kaizen-agent 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +80 -0
- package/agents/kaizen-builder.md +75 -0
- package/agents/kaizen-planner.md +243 -0
- package/agents/kaizen-reviewer.md +127 -0
- package/cli/install.ts +86 -0
- package/commands/kaizen-abort.md +5 -0
- package/commands/kaizen-approve.md +5 -0
- package/commands/kaizen-auto.md +6 -0
- package/commands/kaizen-backlog.md +5 -0
- package/commands/kaizen-init.md +5 -0
- package/commands/kaizen-install.md +5 -0
- package/commands/kaizen-plan.md +6 -0
- package/commands/kaizen-reject.md +6 -0
- package/commands/kaizen-review.md +6 -0
- package/commands/kaizen-run.md +5 -0
- package/commands/kaizen-status.md +5 -0
- package/package.json +35 -0
- package/skills/kaizen/README.md +279 -0
- package/skills/kaizen/SKILL.md +281 -0
- package/skills/kaizen/adapters.md +76 -0
- package/skills/kaizen/config.default.yml +82 -0
- package/skills/kaizen/spec-build.md +80 -0
- package/skills/kaizen/spec-main.md +102 -0
- package/skills/kaizen/spec-plan.md +141 -0
- package/skills/kaizen/spec-review.md +89 -0
- package/skills/kaizen/spec.md +130 -0
- package/skills/kaizen-help/SKILL.md +119 -0
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kaizen-agent",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Staged AI development workflow: plan, human approval, implement, independent review, bounded fix loop.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"kaizen-agent": "./cli/install.ts"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"cli",
|
|
11
|
+
"skills",
|
|
12
|
+
"agents",
|
|
13
|
+
"commands",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"install-links": "bun run cli/install.ts",
|
|
19
|
+
"check": "bun run cli/install.ts --check"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/hfadhlullah/kaizen.git"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"keywords": [
|
|
27
|
+
"claude-code",
|
|
28
|
+
"agent",
|
|
29
|
+
"workflow",
|
|
30
|
+
"skill",
|
|
31
|
+
"codex",
|
|
32
|
+
"antigravity",
|
|
33
|
+
"code-review"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# Kaizen
|
|
2
|
+
|
|
3
|
+
Kaizen is a staged workflow for work that is too big to hand an AI in one go. Instead
|
|
4
|
+
of one agent that plans, writes, and then congratulates itself, the work is split into
|
|
5
|
+
three agents that never share a context window, with human approval stops in between.
|
|
6
|
+
You approve a plan before anything is produced, and an independent reviewer that never
|
|
7
|
+
saw the work being made checks it afterwards.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
request -> PLAN -> [approval] -> IMPLEMENT -> REVIEW -> [fix loop] -> [approval] -> done
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Everything a run knows lives in plain files under `.kaizen/`, so a run can be paused,
|
|
14
|
+
resumed tomorrow, resumed by a different session, or picked up by a different tool.
|
|
15
|
+
|
|
16
|
+
## Why the reviewer runs in a separate context
|
|
17
|
+
|
|
18
|
+
This is the one design decision worth understanding before you use it. An agent that
|
|
19
|
+
watched itself write the code will rationalize it — it remembers why every line seemed
|
|
20
|
+
reasonable, and that memory is exactly what stops it from finding the bug. The kaizen
|
|
21
|
+
reviewer starts fresh. It sees the plan, the diff, and the implementation notes, and
|
|
22
|
+
nothing else. It has no reason to defend anything.
|
|
23
|
+
|
|
24
|
+
The same split is why the planner does not implement: a plan written by the agent that
|
|
25
|
+
is about to do the work bends toward what is easy to write.
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
First get the skill onto your machine: copy or clone this directory somewhere Claude
|
|
30
|
+
can read it. Then ask Claude to install kaizen from there, and it will ask where the
|
|
31
|
+
workflow should live:
|
|
32
|
+
|
|
33
|
+
- **Global** — `~/.claude/skills/kaizen/` and `~/.claude/agents/kaizen-*.md`.
|
|
34
|
+
Available in every project, not shared with your team.
|
|
35
|
+
- **Per-project** — `.claude/skills/kaizen/` and `.claude/agents/kaizen-*.md`,
|
|
36
|
+
committed so the team gets the same workflow.
|
|
37
|
+
|
|
38
|
+
Both can coexist; the project copy wins. Install also offers to write the adapter
|
|
39
|
+
files from [`adapters.md`](adapters.md) so Codex and Antigravity follow the same spec.
|
|
40
|
+
|
|
41
|
+
The workflow is `SKILL.md`, the split spec (`spec.md` core plus `spec-plan.md`,
|
|
42
|
+
`spec-build.md`, `spec-review.md`, `spec-main.md` — each reader takes core plus one),
|
|
43
|
+
`config.default.yml`,
|
|
44
|
+
`adapters.md`, and this README, plus the three agent definitions `kaizen-planner.md`,
|
|
45
|
+
`kaizen-builder.md`, and `kaizen-reviewer.md`.
|
|
46
|
+
|
|
47
|
+
To set a repository up for runs, ask for `kaizen init`. That creates `.kaizen/` with a
|
|
48
|
+
copy of the `spec*.md` files, a config, and the gitignore entry.
|
|
49
|
+
|
|
50
|
+
## Your first run
|
|
51
|
+
|
|
52
|
+
Say what you want, and say the word kaizen:
|
|
53
|
+
|
|
54
|
+
> kaizen: add rate limiting to the public API
|
|
55
|
+
|
|
56
|
+
That is the whole invocation. The skill triggers on the word, so a plain sentence is
|
|
57
|
+
enough — no special syntax, no flags. `SKILL.md` also documents slash forms like
|
|
58
|
+
`/kaizen plan <request>`, `/kaizen status`, and `/kaizen approve`; those are shorthand
|
|
59
|
+
for the same requests, and they only work as literal slash commands if you have
|
|
60
|
+
installed a command file at `~/.claude/commands/kaizen.md`. Nothing here requires one.
|
|
61
|
+
Saying "kaizen status" or "approve the plan" works either way.
|
|
62
|
+
|
|
63
|
+
Then the run stops twice, and both stops want something specific from you.
|
|
64
|
+
|
|
65
|
+
**Stop one — the plan.** You get a written plan: what is wrong today, what would be
|
|
66
|
+
true instead, the approach chosen, what was rejected and why, and a plain-bullet
|
|
67
|
+
**Work list** of what will actually be done. If the request had genuine ambiguity, the
|
|
68
|
+
plan ends with open questions, and they reach you as a pick list of two to four
|
|
69
|
+
concrete options rather than an open prompt. You can always type something else.
|
|
70
|
+
|
|
71
|
+
Three things newcomers do not expect:
|
|
72
|
+
|
|
73
|
+
- **"Yes, but change X" is a normal answer.** You are not limited to approve or
|
|
74
|
+
reject. Approving with a modification — a different value, a dropped step — is
|
|
75
|
+
recorded in the approval file and binds the builder.
|
|
76
|
+
- **Rejecting is not a failure.** The reason is written down and handed back to the
|
|
77
|
+
stage that produced the artifact, which revises and re-presents.
|
|
78
|
+
- **The planner also lists out-of-scope suggestions** — things it noticed but did not
|
|
79
|
+
fold into the plan. Each is a separate yes or no. Saying nothing means no.
|
|
80
|
+
|
|
81
|
+
Nothing is produced until you clear this stop.
|
|
82
|
+
|
|
83
|
+
**Stop two — the review.** After the work is done, the reviewer reports findings with
|
|
84
|
+
severities, and the run stops before calling the work done. If a finding is below the
|
|
85
|
+
auto-fix threshold, or still open when the fix rounds run out, it is reported to you
|
|
86
|
+
rather than quietly patched.
|
|
87
|
+
|
|
88
|
+
## What a run decided not to do
|
|
89
|
+
|
|
90
|
+
Both stops throw things away. The planner's out-of-scope suggestions you did not take,
|
|
91
|
+
the low findings nobody fixed, the "later" you said at an approval — all real work, all
|
|
92
|
+
previously surviving only in the conversation.
|
|
93
|
+
|
|
94
|
+
Kaizen writes them down instead, into `06-backlog.md` inside the run that produced
|
|
95
|
+
them, so an item sits next to the plan and the review that explain it. You do not
|
|
96
|
+
maintain this file; it is written at the two moments the run already writes to disk —
|
|
97
|
+
recording the plan approval, and marking the run done — so there is nothing to
|
|
98
|
+
remember.
|
|
99
|
+
|
|
100
|
+
Every item is `open`, `done`, or `rejected`. **Rejected is a real answer**: most
|
|
101
|
+
suggestions are not worth doing, and without a way to decline one it stays on the list
|
|
102
|
+
forever. Rejecting takes a reason, which is what stops the same idea coming back three
|
|
103
|
+
runs later. Closed items stay in their run's file as record and are never printed
|
|
104
|
+
again.
|
|
105
|
+
|
|
106
|
+
Two commands read across all of it:
|
|
107
|
+
|
|
108
|
+
- **`kaizen backlog`** — every open item, grouped by the run it came from, newest
|
|
109
|
+
first, with items rescued from pruned runs last under *Orphaned*. Nothing done,
|
|
110
|
+
nothing rejected.
|
|
111
|
+
- **`kaizen status`** — every run you have, in four groups: waiting on you, in flight,
|
|
112
|
+
done, and abandoned, with the open backlog count at the bottom.
|
|
113
|
+
|
|
114
|
+
A run you abort is abandoned, not outstanding: it sits in its own group and its backlog
|
|
115
|
+
items stop being printed and stop being counted.
|
|
116
|
+
|
|
117
|
+
Status is read live from each run's `state.json`, so nothing gets renamed or moved when
|
|
118
|
+
a run finishes and no path you have written down elsewhere ever breaks.
|
|
119
|
+
|
|
120
|
+
One thing to know about pruning: `state.keep_runs` eventually deletes old run
|
|
121
|
+
directories. Before a run goes, its still-open items are moved into
|
|
122
|
+
`.kaizen/backlog.md` — that file exists only as an orphanage. `kaizen backlog` reads it
|
|
123
|
+
too and prints those items last, under *Orphaned*, so nothing outstanding disappears
|
|
124
|
+
just because its run did. Items already done or rejected are deleted with their run,
|
|
125
|
+
which is the point.
|
|
126
|
+
|
|
127
|
+
## A real run, start to finish
|
|
128
|
+
|
|
129
|
+
This one actually happened. The whole request was one line, said in passing:
|
|
130
|
+
|
|
131
|
+
> for this dropdown omarchy terminal can we make it much more to the bottom?
|
|
132
|
+
|
|
133
|
+
**Intake** wrote that down verbatim in `00-request.md`, along with what it could
|
|
134
|
+
establish on its own: the script is `~/.local/bin/omarchy-dropdown`, bound to
|
|
135
|
+
`SUPER + grave`, and its height comes from `OMARCHY_DROPDOWN_HEIGHT`, default `0.55`.
|
|
136
|
+
|
|
137
|
+
**The plan** noticed the request had two readings — the panel *extending* further down
|
|
138
|
+
versus the whole panel *sitting* lower — and, rather than asking which, argued for the
|
|
139
|
+
first and said so plainly:
|
|
140
|
+
|
|
141
|
+
> Reading (2) already has a knob — `GAP` (`omarchy-dropdown:13`) — and it does not do
|
|
142
|
+
> what the phrase wants. [...] Setting `GAP=200` moves the top down to y=230 but shrinks the height to 555,
|
|
143
|
+
> putting the bottom edge at 785 — *higher* than today.
|
|
144
|
+
|
|
145
|
+
It proposed `HEIGHT_FRACTION` `0.55 → 0.80`, and listed fixing the `GAP` asymmetry as
|
|
146
|
+
an out-of-scope suggestion rather than doing it.
|
|
147
|
+
|
|
148
|
+
**The approval** is the interesting part, because it was neither yes nor no:
|
|
149
|
+
|
|
150
|
+
> **Value changed: 0.80 → 0.70.** The user chose a smaller increase than proposed
|
|
151
|
+
> [...] Wherever the plan specifies `HEIGHT_FRACTION=0.80`, use **`0.70`** instead.
|
|
152
|
+
> Nothing else changes: same file, same three steps, same verification.
|
|
153
|
+
|
|
154
|
+
The out-of-scope `GAP` fix was explicitly not approved, which made it off-limits for
|
|
155
|
+
the rest of the run.
|
|
156
|
+
|
|
157
|
+
**The implementation** changed one token, verified the geometry arithmetic instead of
|
|
158
|
+
toggling the live window, and reported the thing it did not do:
|
|
159
|
+
|
|
160
|
+
> Live steps 3-6 of the plan's verification [...] were not run: this run was
|
|
161
|
+
> explicitly instructed not to toggle the live dropdown.
|
|
162
|
+
|
|
163
|
+
**The review** re-derived the numbers independently, confirmed the file said `0.70` and
|
|
164
|
+
not `0.80`, confirmed the `GAP` code was untouched — and found one thing nobody had
|
|
165
|
+
considered: a second monitor configured as portrait might report an untransformed
|
|
166
|
+
height, in which case the larger fraction could overflow where the old one did not.
|
|
167
|
+
|
|
168
|
+
> `FINDINGS: 0 critical, 0 high, 0 medium, 1 low`
|
|
169
|
+
|
|
170
|
+
Low is below the default fix threshold, so it was not auto-fixed. It was reported, with
|
|
171
|
+
the exact command to settle it when that monitor is next plugged in. The reviewer also
|
|
172
|
+
left a line in `memory.md`, which every later run in this directory reads:
|
|
173
|
+
|
|
174
|
+
> `GAP` cannot — `geometry()` subtracts `gap * 2` from the height but adds `gap` only
|
|
175
|
+
> once to `y`, so raising GAP moves the bottom edge *up*. Unfixed as of 2026-09-02.
|
|
176
|
+
|
|
177
|
+
One-line request, six files, one real finding, one lesson that outlives the run.
|
|
178
|
+
|
|
179
|
+
## Kaizen is not only for code
|
|
180
|
+
|
|
181
|
+
Every stage adapts to the **track** — the kind of work a run is doing, which is what
|
|
182
|
+
decides what *deliverable*, *verification*, and *finding* mean. A chapter, a landing
|
|
183
|
+
page, a migration runbook, and a research memo each get a reviewer that checks the
|
|
184
|
+
right things; a reviewer hunting race conditions in a manuscript is worse than none.
|
|
185
|
+
|
|
186
|
+
The track is inferred from your request and stated back to you in the plan, so you
|
|
187
|
+
correct a reading instead of categorizing your own work. You are never asked "is this
|
|
188
|
+
software or writing?"
|
|
189
|
+
|
|
190
|
+
## Configuration
|
|
191
|
+
|
|
192
|
+
Defaults live in [`config.default.yml`](config.default.yml). Copy it to
|
|
193
|
+
`.kaizen/config.yml` in a repository and override only the keys you care about;
|
|
194
|
+
anything absent falls back to the defaults.
|
|
195
|
+
|
|
196
|
+
| Key | Default | Change it when |
|
|
197
|
+
|---|---|---|
|
|
198
|
+
| `mode` | `approve` | You want `plan-only` to think without building, `auto` to run unattended, or `review-only` to audit existing work |
|
|
199
|
+
| `approvals.plan` | `true` | Rarely. This is the stop that makes the workflow worth running |
|
|
200
|
+
| `approvals.review` | `false` | Set `true` to add a second human stop after the review; with `auto_fix` on it mostly re-approves a report you are already reading |
|
|
201
|
+
| `approvals.each_file` | `false` | You want to confirm every single file edit. Maximum control, slowest |
|
|
202
|
+
| `auto_fix.enabled` | `true` | Set `false` and every finding becomes your decision instead |
|
|
203
|
+
| `auto_fix.min_severity` | `high` | Lower to `medium` or `low` to have more auto-fixed; raise findings you see instead of auto-fixing |
|
|
204
|
+
| `auto_fix.max_iterations` | `2` | Fix/recheck rounds before whatever is left is escalated to you |
|
|
205
|
+
| `review.memory_max_lines` | `100` | The cap on `memory.md`, which every stage of every run reads. Raise only if the lessons are genuinely all load-bearing |
|
|
206
|
+
| `git.auto_commit` | `false` | Leave it. Kaizen does not commit or push unless you ask |
|
|
207
|
+
| `track.default` | `""` (inferred) | A repo that is always one kind of work, e.g. a docs repo |
|
|
208
|
+
| `backlog.enabled` | `true` | Set `false` to skip both backlog capture points; the run still executes, just without a `06-backlog.md` |
|
|
209
|
+
| `backlog.file` | `06-backlog.md` | The per-run file name. Rarely. |
|
|
210
|
+
| `backlog.statuses` | `[open, done, rejected]` | Rarely. Only `open` items are printed |
|
|
211
|
+
| `backlog.orphan_file` | `backlog.md` | Where open items go when their run is pruned |
|
|
212
|
+
| `state.keep_runs` | `20` | You want a longer or shorter run history |
|
|
213
|
+
|
|
214
|
+
Mode never overrides a refusal: destructive or irreversible actions still get confirmed
|
|
215
|
+
even in `auto`.
|
|
216
|
+
|
|
217
|
+
## Where your files live
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
.kaizen/
|
|
221
|
+
spec.md # core contract, copied in by init
|
|
222
|
+
spec-plan.md # per-stage contracts; each reader takes core + one
|
|
223
|
+
spec-build.md
|
|
224
|
+
spec-review.md
|
|
225
|
+
spec-main.md
|
|
226
|
+
config.yml
|
|
227
|
+
memory.md # cross-run lessons, appended by the reviewer
|
|
228
|
+
backlog.md # orphanage only: open items rescued before pruning
|
|
229
|
+
runs/
|
|
230
|
+
2026-09-02-add-oauth/
|
|
231
|
+
00-request.md # the original request, verbatim
|
|
232
|
+
01-plan.md
|
|
233
|
+
02-approval.md # decisions, with reasons and timestamps
|
|
234
|
+
03-impl.md # what changed, which files, what was skipped
|
|
235
|
+
04-review.md # findings, severity-tagged
|
|
236
|
+
05-iterations/
|
|
237
|
+
01-fix.md
|
|
238
|
+
01-recheck.md
|
|
239
|
+
06-backlog.md # what this run deliberately did not do
|
|
240
|
+
state.json
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
`state.json` is the resume point — stage, mode, and what the run is waiting on:
|
|
244
|
+
|
|
245
|
+
```json
|
|
246
|
+
{
|
|
247
|
+
"id": "2026-09-02-add-oauth",
|
|
248
|
+
"mode": "approve",
|
|
249
|
+
"stage": "review",
|
|
250
|
+
"awaiting": "approvals.review",
|
|
251
|
+
"iteration": 1,
|
|
252
|
+
"updated": "2026-09-02T14:31:00+07:00"
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
If a repository has no `.kaizen/`, state goes to `~/.kaizen/` keyed by working
|
|
257
|
+
directory instead.
|
|
258
|
+
|
|
259
|
+
Run state is per-person and not worth committing; the workflow itself is. `init` writes
|
|
260
|
+
this gitignore stanza:
|
|
261
|
+
|
|
262
|
+
```gitignore
|
|
263
|
+
.kaizen/*
|
|
264
|
+
!.kaizen/spec*.md
|
|
265
|
+
!.kaizen/config.yml
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Where to go next
|
|
269
|
+
|
|
270
|
+
- [`spec.md`](spec.md) + [`spec-plan.md`](spec-plan.md), [`spec-build.md`](spec-build.md),
|
|
271
|
+
[`spec-review.md`](spec-review.md), [`spec-main.md`](spec-main.md) — the tool-neutral
|
|
272
|
+
stage contract, split so each reader loads only core plus its own stage: exactly what
|
|
273
|
+
that stage reads, writes, and must not do. If anything here and the spec disagree, the spec
|
|
274
|
+
wins.
|
|
275
|
+
- [`config.default.yml`](config.default.yml) — every key with its default and a comment.
|
|
276
|
+
- [`adapters.md`](adapters.md) — running kaizen from Codex or Antigravity, and handing a
|
|
277
|
+
half-finished run between tools.
|
|
278
|
+
- [`SKILL.md`](SKILL.md) — the instructions the agent itself follows. Read it if you want
|
|
279
|
+
to know what Claude is doing between your two approval stops.
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kaizen
|
|
3
|
+
description: >
|
|
4
|
+
Staged AI development workflow: plan, human approval, implementation, then
|
|
5
|
+
independent bug/security review with a bounded fix loop. Each stage runs as its own
|
|
6
|
+
subagent with clean context, and all state lives in a portable `.kaizen/` directory so
|
|
7
|
+
a run can be resumed later, by another session, or by another AI tool (Codex,
|
|
8
|
+
Antigravity). Use when the user says "kaizen", "/kaizen", asks to plan-then-build-then-review
|
|
9
|
+
a change, wants approval steps before code is written, or wants to resume or check an
|
|
10
|
+
existing kaizen run. Also use to install the workflow into a repository.
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Kaizen
|
|
14
|
+
|
|
15
|
+
A staged workflow for non-trivial development work:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
request -> PLAN -> [approval] -> IMPLEMENT -> REVIEW -> [fix loop] -> [approval] -> done
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Three separate subagents do the work. They never share a context window, which is
|
|
22
|
+
the point: a reviewer that watched the code being written will rationalize it, a
|
|
23
|
+
reviewer that sees only the diff and the plan will not.
|
|
24
|
+
|
|
25
|
+
The stage contract is split so no reader loads a stage it is not running:
|
|
26
|
+
[`spec.md`](spec.md) is the core (track, intake, resume) and every reader takes it,
|
|
27
|
+
plus exactly one of [`spec-plan.md`](spec-plan.md), [`spec-build.md`](spec-build.md),
|
|
28
|
+
[`spec-review.md`](spec-review.md), or [`spec-main.md`](spec-main.md) — the main
|
|
29
|
+
thread's own file. Read core plus your stage before running it; do not read the
|
|
30
|
+
others. Configuration defaults are in [`config.default.yml`](config.default.yml).
|
|
31
|
+
Porting the workflow to Codex or Antigravity is covered in [`adapters.md`](adapters.md).
|
|
32
|
+
|
|
33
|
+
## Commands
|
|
34
|
+
|
|
35
|
+
| Invocation | Action |
|
|
36
|
+
|---|---|
|
|
37
|
+
| `/kaizen <request>` | Start a new run in the configured mode (default: `approve`) |
|
|
38
|
+
| `/kaizen plan <request>` | Start a run and stop after the plan (`plan-only`) |
|
|
39
|
+
| `/kaizen auto <request>` | Start a run in `auto` mode: every stage back to back, no approval stops |
|
|
40
|
+
| `/kaizen run` | Resume the current run and execute the approved plan |
|
|
41
|
+
| `/kaizen review [target]` | Review-only: audit existing code, no plan, no implementation (`review-only`) |
|
|
42
|
+
| `/kaizen status` | List every run grouped waiting-on-you / in flight / done / abandoned, plus the open backlog count |
|
|
43
|
+
| `/kaizen backlog` | Print the open backlog items across all runs, grouped by source run, with rescued items last under `Orphaned` |
|
|
44
|
+
| `/kaizen approve` | Approve whatever the current run is waiting on |
|
|
45
|
+
| `/kaizen reject <reason>` | Reject it; the reason is fed back to the stage that produced it |
|
|
46
|
+
| `/kaizen abort` | Mark the current run abandoned |
|
|
47
|
+
| `/kaizen init` | Install `.kaizen/` with the `spec*.md` files, config, and the gitignore entry into the current repository |
|
|
48
|
+
| `/kaizen install` | Install the workflow itself globally or per-project (see below) |
|
|
49
|
+
|
|
50
|
+
If the user typed `/kaizen` with no argument and a run is in progress, treat it as
|
|
51
|
+
`/kaizen status`. If no run is in progress, ask what they want to build.
|
|
52
|
+
|
|
53
|
+
## Before doing anything
|
|
54
|
+
|
|
55
|
+
1. Locate the state directory: `.kaizen/` in the repository root, else `~/.kaizen/`
|
|
56
|
+
keyed by working directory. If neither exists and the user is starting work, run
|
|
57
|
+
`/kaizen init` first: it creates `.kaizen/` with a copy of the `spec*.md` files, a config, and
|
|
58
|
+
the gitignore entry (see [`adapters.md`](adapters.md)).
|
|
59
|
+
2. Read `.kaizen/config.yml`, falling back to `config.default.yml` in this skill for
|
|
60
|
+
any key it does not set.
|
|
61
|
+
3. Read `.kaizen/runs/<current>/state.json` if a run is active. Never assume the
|
|
62
|
+
stage from conversation memory — the run may have been advanced by another tool
|
|
63
|
+
or another session.
|
|
64
|
+
4. Read `.kaizen/memory.md` if present. It holds cross-run lessons and carries real
|
|
65
|
+
weight: it is what previous reviewers learned about this codebase.
|
|
66
|
+
|
|
67
|
+
## Modes
|
|
68
|
+
|
|
69
|
+
Set by `mode` in config, overridable per invocation.
|
|
70
|
+
|
|
71
|
+
- **`plan-only`** — produce the plan, write it, stop. No code is touched.
|
|
72
|
+
- **`approve`** (default) — stop at every approval enabled in config and wait for an
|
|
73
|
+
explicit human decision.
|
|
74
|
+
- **`auto`** — run every stage back to back with no approval, report at the end. The fix
|
|
75
|
+
loop still respects `max_iterations`.
|
|
76
|
+
- **`review-only`** — skip plan and implementation, run the reviewer against existing
|
|
77
|
+
code or a diff.
|
|
78
|
+
|
|
79
|
+
Mode never overrides a refusal: destructive or irreversible actions still get
|
|
80
|
+
confirmed even in `auto`.
|
|
81
|
+
|
|
82
|
+
## Approvals
|
|
83
|
+
|
|
84
|
+
Approvals are configured, not hardcoded. Each enabled approval halts the run, writes what it
|
|
85
|
+
is waiting for into `state.json`, and reports to the user. The run only advances on
|
|
86
|
+
an explicit `/kaizen approve` or a clear approval in conversation.
|
|
87
|
+
|
|
88
|
+
- `approvals.plan` — after the plan, before any code is written. On by default.
|
|
89
|
+
- `approvals.review` — after the review passes, before the work is called done. Off by
|
|
90
|
+
default: with `auto_fix` on, it mostly asks for approval of a report being read anyway.
|
|
91
|
+
- `approvals.each_file` — confirm each file edit individually. Off by default; slow.
|
|
92
|
+
|
|
93
|
+
A rejected approval is not a failure, and it is not always the same action. Two shapes:
|
|
94
|
+
**revise** ("do it differently") sends the plan back to the planner, which produces a
|
|
95
|
+
new version and returns to this same approval. **Kill** ("not doing this") means the
|
|
96
|
+
request itself was wrong, not the approach — set `stage: "abandoned"` and stop, no
|
|
97
|
+
revision to make. The reason says which; state the reading taken in `02-approval.md`
|
|
98
|
+
when it is not obvious. See *Plan approval* in [`spec-plan.md`](spec-plan.md) for the full rule.
|
|
99
|
+
|
|
100
|
+
**Asking the user anything:** use AskUserQuestion with 2–4 concrete options, taken
|
|
101
|
+
from the options the planner wrote into the plan. Subagents cannot prompt the user,
|
|
102
|
+
so every question reaches them through you. Do not add an "other" option — free text
|
|
103
|
+
is always available. Reserve plain prose questions for things that genuinely have no
|
|
104
|
+
discrete answers.
|
|
105
|
+
|
|
106
|
+
**Before the builder runs:** show the plan's **Work list** — plain bullets of what
|
|
107
|
+
will actually be done. It is the last thing the user sees before anything is
|
|
108
|
+
produced, so show it even when they have already approved the plan in conversation.
|
|
109
|
+
|
|
110
|
+
## The fix loop
|
|
111
|
+
|
|
112
|
+
When the reviewer reports findings, behavior depends on config:
|
|
113
|
+
|
|
114
|
+
- `auto_fix.enabled: false` — always stop and hand every finding to the user as a
|
|
115
|
+
decision, listed by the reviewer's number so the user can name a subset. Nothing is
|
|
116
|
+
fixed automatically.
|
|
117
|
+
- `auto_fix.enabled: true` — the builder fixes findings at or above
|
|
118
|
+
`auto_fix.min_severity` (default `high`), the reviewer re-checks, repeating up to
|
|
119
|
+
`auto_fix.max_iterations` (default 2). Findings below the threshold, and anything
|
|
120
|
+
still open when iterations run out, are reported to the user rather than silently
|
|
121
|
+
dropped.
|
|
122
|
+
|
|
123
|
+
Every iteration is written to `runs/<id>/05-iterations/` so the loop is auditable.
|
|
124
|
+
|
|
125
|
+
## Backlog and status
|
|
126
|
+
|
|
127
|
+
Each run keeps its own backlog at `runs/<id>/06-backlog.md`. You write it, in the main
|
|
128
|
+
thread, at two writes that already happen: `02-approval.md` at the plan approval
|
|
129
|
+
(out-of-scope suggestions not folded into the approved scope, and anything cut at the
|
|
130
|
+
approval) and `stage: "done"` at the final approval (findings still open, findings
|
|
131
|
+
below the fix threshold, and the builder's out-of-scope notes). No subagent writes it.
|
|
132
|
+
The full rules are in [`spec-main.md`](spec-main.md).
|
|
133
|
+
|
|
134
|
+
Items are one line each, `- <status>: <item text>`, with `<status>` one of `open`,
|
|
135
|
+
`done`, or `rejected`. Findings keep the reviewer's line verbatim. `rejected` always
|
|
136
|
+
carries a reason after a `|`. Closing an item edits its status in place; the line
|
|
137
|
+
stays in the run's file as record.
|
|
138
|
+
|
|
139
|
+
`/kaizen backlog` reads every `runs/*/06-backlog.md` at read time and prints the `open`
|
|
140
|
+
items only, grouped by source run, newest run first. There is no central backlog file
|
|
141
|
+
to keep in sync. `<state.dir>/backlog.md` is an orphanage and nothing more: before
|
|
142
|
+
`state.keep_runs` prunes a run, move that run's still-open items into it. `/kaizen
|
|
143
|
+
backlog` reads that file too and prints its open items last, under an **Orphaned**
|
|
144
|
+
group, so a rescued item stays visible after its run is gone.
|
|
145
|
+
|
|
146
|
+
**`/kaizen backlog` and `/kaizen status` are read-only.** They print; they never edit
|
|
147
|
+
a `06-backlog.md` or `state.json`, even when reading one turns up an inconsistency
|
|
148
|
+
(a stale `open` item already closed elsewhere, a duplicate, a bad reference). Report
|
|
149
|
+
what looks wrong as part of the output and ask before touching anything — fixing it
|
|
150
|
+
unasked is exactly the scope creep the rest of this spec exists to prevent, applied to
|
|
151
|
+
kaizen's own bookkeeping instead of a user's code.
|
|
152
|
+
|
|
153
|
+
`/kaizen status` reads each `runs/*/state.json` live and prints every run in four
|
|
154
|
+
groups:
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
Waiting on you — awaiting is non-null and stage is not "abandoned"
|
|
158
|
+
In flight — awaiting is null and stage is neither "done" nor "abandoned"
|
|
159
|
+
Done — stage is "done"
|
|
160
|
+
Abandoned — stage is "abandoned" (set by /kaizen abort)
|
|
161
|
+
|
|
162
|
+
Backlog: <n> open
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The count is every open item across all runs plus the orphanage. An abandoned run's
|
|
166
|
+
backlog items are not open work: leave them in place, and do not print or count them.
|
|
167
|
+
|
|
168
|
+
Each line is the run id, its stage, and what it is awaiting. Grouping is derived from
|
|
169
|
+
`state.json` at read time, never from the directory name — run directories are flat and
|
|
170
|
+
are never renamed or moved, so a path written into another file cannot break.
|
|
171
|
+
|
|
172
|
+
## Running a stage
|
|
173
|
+
|
|
174
|
+
Each stage runs as a subagent via the Agent tool, with the agent type named below.
|
|
175
|
+
Pass it the run directory path and let it read its own inputs from there — do not
|
|
176
|
+
paste plans or diffs into the prompt, since the file is the shared source of truth
|
|
177
|
+
across tools. Name its spec files in the prompt: core `spec.md` plus its own stage
|
|
178
|
+
file, never the whole set.
|
|
179
|
+
|
|
180
|
+
| Stage | Agent type | Writes |
|
|
181
|
+
|---|---|---|
|
|
182
|
+
| Plan | `kaizen-planner` | `01-plan.md` |
|
|
183
|
+
| Implement | `kaizen-builder` | `03-impl.md` + the actual code changes |
|
|
184
|
+
| Review | `kaizen-reviewer` | `04-review.md` |
|
|
185
|
+
|
|
186
|
+
After a subagent returns, update `state.json` yourself in the main thread. Subagents
|
|
187
|
+
report; the main thread owns the state machine.
|
|
188
|
+
|
|
189
|
+
**Scope precisely, don't scope narrow.** Each subagent starts cold — no context from
|
|
190
|
+
you carries over except what the prompt names. List exactly the files this stage's
|
|
191
|
+
task actually touches; don't default to "read everything" for safety. But cutting a
|
|
192
|
+
file the task genuinely needs is worse than the tokens it would have cost: a
|
|
193
|
+
under-scoped subagent produces a wrong plan or misses a real defect, which costs a fix
|
|
194
|
+
iteration — more tokens than the read would have. Precise beats narrow.
|
|
195
|
+
|
|
196
|
+
Relay what matters from each subagent's report to the user — their output is not
|
|
197
|
+
shown automatically.
|
|
198
|
+
|
|
199
|
+
## State layout
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
.kaizen/
|
|
203
|
+
spec.md # core contract, copied in by init
|
|
204
|
+
spec-plan.md # per-stage contracts; each reader takes core + one
|
|
205
|
+
spec-build.md
|
|
206
|
+
spec-review.md
|
|
207
|
+
spec-main.md
|
|
208
|
+
config.yml
|
|
209
|
+
memory.md # cross-run lessons, appended by the reviewer
|
|
210
|
+
backlog.md # orphanage only: open items rescued before pruning
|
|
211
|
+
runs/
|
|
212
|
+
2026-09-02-add-oauth/
|
|
213
|
+
00-request.md # the original request, verbatim
|
|
214
|
+
01-plan.md
|
|
215
|
+
02-approval.md # decisions, with reasons and timestamps
|
|
216
|
+
03-impl.md # what changed, which files, what was skipped
|
|
217
|
+
04-review.md # findings, numbered and severity-tagged
|
|
218
|
+
05-iterations/
|
|
219
|
+
01-fix.md
|
|
220
|
+
01-recheck.md
|
|
221
|
+
06-backlog.md # what this run deliberately did not do
|
|
222
|
+
state.json
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
`state.json` is the resume point:
|
|
226
|
+
|
|
227
|
+
```json
|
|
228
|
+
{
|
|
229
|
+
"id": "2026-09-02-add-oauth",
|
|
230
|
+
"mode": "approve",
|
|
231
|
+
"stage": "review",
|
|
232
|
+
"awaiting": "approvals.review",
|
|
233
|
+
"iteration": 1,
|
|
234
|
+
"updated": "2026-09-02T14:31:00+07:00"
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`init` adds a gitignore entry that ignores run state but keeps the workflow: it
|
|
239
|
+
ignores `.kaizen/*` and un-ignores `.kaizen/spec*.md` and `.kaizen/config.yml`, which
|
|
240
|
+
are meant to be committed (see [`adapters.md`](adapters.md)).
|
|
241
|
+
|
|
242
|
+
## Install
|
|
243
|
+
|
|
244
|
+
`/kaizen install` asks where the workflow should live: **global** (this machine, every
|
|
245
|
+
project) or **per-project** (this repo, committed, shared with the team). Both can
|
|
246
|
+
coexist; the project copy wins when present.
|
|
247
|
+
|
|
248
|
+
**Global.** Kaizen's source of truth is the repo at `~/kaizen` (symlinked in on this
|
|
249
|
+
machine). Installing or updating global kaizen means that repo is current and linked:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
[ -d ~/kaizen ] && (cd ~/kaizen && git pull) || git clone <kaizen repo url> ~/kaizen
|
|
253
|
+
mkdir -p ~/.claude/skills ~/.claude/agents
|
|
254
|
+
ln -sfn ~/kaizen/skills/kaizen ~/.claude/skills/kaizen
|
|
255
|
+
for f in kaizen-planner kaizen-builder kaizen-reviewer; do
|
|
256
|
+
ln -sfn ~/kaizen/agents/$f.md ~/.claude/agents/$f.md
|
|
257
|
+
done
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Symlinks, not copies — future `git pull` in `~/kaizen` updates every project on this
|
|
261
|
+
machine at once. This only works because `~/kaizen` is a repo the installing user
|
|
262
|
+
controls; it is not something to hand a teammate.
|
|
263
|
+
|
|
264
|
+
**Per-project.** A teammate cloning this repo does not have access to `~/kaizen` (it
|
|
265
|
+
can be private, or simply not theirs), so the project copy must be self-contained —
|
|
266
|
+
real files, not symlinks, committed into the project:
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
mkdir -p .claude/skills/kaizen .claude/agents
|
|
270
|
+
cp ~/kaizen/skills/kaizen/*.md ~/kaizen/skills/kaizen/*.yml .claude/skills/kaizen/
|
|
271
|
+
cp ~/kaizen/agents/kaizen-*.md .claude/agents/
|
|
272
|
+
git add .claude/skills/kaizen .claude/agents/kaizen-*.md
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Then commit. Updating a per-project copy later means re-running the `cp` lines against
|
|
276
|
+
a current `~/kaizen` and committing the diff — there is no live link to keep it in
|
|
277
|
+
sync automatically, by design.
|
|
278
|
+
|
|
279
|
+
`install` also offers to write the adapter files from [`adapters.md`](adapters.md) so
|
|
280
|
+
Codex and Antigravity follow the same spec, per-project only (a global adapter file has
|
|
281
|
+
nowhere sensible to live).
|