@javaidnaik/loopai
v0.7.0
Published
Loop engineering for AI coding agents. One canonical loop, installed into Claude Code, Gemini CLI, Codex CLI, or Cursor.
Maintainers
Readme
loopAI
Loop engineering for AI coding agents. One canonical loop, installed into whichever tool you use: Claude Code, Gemini CLI, Codex CLI, or Cursor.
You stop hand-prompting your agent. You answer a few questions once, and a standing loop does the work and checks itself. The same three commands and the exact same loop logic run in every tool.
init set up loop engineering in a repo (new or existing), never edits code
grill answer a few questions -> a precise, safe loop spec
engineer run it: a maker phase and a checker phase each round, with a human gate
compass unsure which loop fits? it asks, then points you to the right command
baton compact the current work into a handoff doc for another session
harvest turn a finished loop into a PRD or a set of grabbable issues
guard set up git guardrails that block dangerous commands during a loopInstall the commands
First install loopAI once, globally:
npm install -g @javaidnaik/loopaiThen, from the root of the project you want to add loops to, run:
loopai install --tool claude # or gemini, codex, cursor, or all(Codex installs globally to ~/.codex/prompts, so for Codex you can run it from
anywhere.)
Where the files land, and how you invoke the commands:
| Tool | Files written | Invoke as |
|-------------|----------------------------------------|-----------|
| Claude Code | .claude/commands/loop/*.md | /loop:init /loop:grill /loop:engineer <slug> |
| Gemini CLI | .gemini/commands/loop/*.toml | /loop:init /loop:grill /loop:engineer <slug> |
| Codex CLI | ~/.codex/prompts/loop-*.md (global) | /loop-init /loop-grill /loop-engineer <slug> |
| Cursor | .cursor/commands/loop-*.md | /loop-init /loop-grill /loop-engineer <slug> |
Codex prompts are global (they live in your home directory), so you install once and they work in every project. The other three install per project.
Use it
- Run the init command once in your repo. It scaffolds
.loops/and writes aCONTEXT.mdso the loop understands your stack. It never touches your code. - Run grill. It interviews you one question at a time and writes a spec to
.loops/specs/<slug>.json. - Run engineer with that slug. Each round, a maker phase does the work and a checker phase verifies it against your rules. A human gate stops anything final until you approve.
Open .loops/state/<slug>.STATE.md afterward to read the full round-by-round
record.
Real subagent isolation (Claude Code only)
engineer runs the maker and checker phases in one session, one model
switching hats. That is portable across every tool, but it means the checker
still shares a context window with the maker it is supposed to be skeptical of.
If you installed loopAI as a native Claude Code plugin, you also get
loopai:maker and loopai:checker, two real subagents with their own tool
access and their own context window. /loopai:loop:engineer-agents <slug>
runs the same round loop as engineer, but dispatches each phase to one of
these subagents via the Task tool instead of role-switching in place. The
checker genuinely cannot see the maker's reasoning, only the shared state file
you would read yourself.
This command only exists for Claude Code, because the Task tool and custom
subagents are a Claude Code feature. Gemini CLI, Codex, and Cursor stay on
engineer. Use engineer-agents when you want the strictest possible
separation for a loop that matters; use engineer everywhere else.
Skip the interview: preset specs
Five proven loops ship with the CLI. Drop one in and run it, no grilling needed:
loopai spec # list presets
loopai spec readme-sync # the safe first loop (report-only)
loopai spec dep-bump # propose safe dependency bumps (report-only)
loopai spec pr-review # strict senior-engineer review of your branch
loopai spec test-first # TDD loop: red test first, then the fix
loopai spec bug-hunt # reproduce, minimise, fixOpen the spec after dropping it and adjust rules or inputs to your repo.
Check yourself: doctor and list
loopai doctor # is this repo loop-ready? scores setup, specs, test command
loopai list # every spec here, with its last verdictLoops that run without you: cron
The whole promise of loop engineering is loops that run while you do other
work. cron emits a GitHub Action that runs a spec on a schedule and opens
the report as a GitHub issue:
loopai cron dep-bump --agent claude --schedule "0 6 * * 1"Scheduled runs are forced to L1 report-only no matter what the spec says, because there is no human at the gate. You still need to wire your agent CLI's headless auth on the runner before enabling the workflow. Full setup for both Claude and Gemini, with a sanity checklist, is in docs/HEADLESS.md.
Run loops right in your terminal
You do not need to be inside a chat session. run drives the whole loop from
your shell using the Claude or Gemini CLI headlessly:
loopai run readme-sync --agent claudeYou watch the maker and checker rounds stream, answer the human gate with a
keypress, and get the full round log in .loops/state/<slug>.STATE.md. L1
specs instruct the maker to propose changes only, never edit files. run
writes .loops/.phase-lock.json itself around each phase, so if the repo also
has loopAI installed as a native Claude Code plugin, the spawned claude -p
calls get that L1 rule hook-enforced (see Autonomy levels below), not just
instructed. npm install -g alone does not install the plugin, /plugin
install does, they are separate steps.
Cross-model checking
run can put the maker and checker on different models, so the checker is not
marking its own homework even at the CLI level:
loopai run pr-review --maker claude --checker gemini--maker/--checker override --agent for just that phase. A spec can also
pin its own pairing with "maker" and "checker" fields in the JSON, which
win over --agent but lose to an explicit --maker/--checker flag on the
command line. loopai doctor checks that any maker/checker fields in your
specs are valid.
Every run is recorded, and stats tells you which loops are earning trust:
loopai stats
# readme-sync runs: 5 pass rate: 100% avg rounds: 1.4 <- earning L2/L3 trustOnce a loop has run with more than one maker/checker pairing, stats breaks
out the pass rate per pairing too, so you can see whether a stricter checker
model is actually catching more:
pr-review
runs: 8 pass rate: 75% avg rounds: 2.1 last: 2026-07-01
checker claude -> claude: 100% pass (3 runs)
checker claude -> gemini: 60% pass (5 runs)A loop with three or more runs at a 100% pass rate is your signal to consider raising its autonomy. That decision now comes from data, not vibes.
After updating the package (npm update -g @javaidnaik/loopai), refresh the
command files installed in your tools with one command:
loopai upgradeIt remembers which tools you installed for and brings their command files up to the current version.
Proof it works: examples
The examples/ folder holds three recorded runs with full round logs: a
test-fixing loop where the checker catches a regression the maker introduced,
a report-only dependency bump, and a one-round README sync. Read them to watch
the maker and checker argue and converge.
Why one source
The loop logic lives in one place: the three prompt files in prompts/. The
installer wraps them in each tool's required format (markdown frontmatter for
Claude and Cursor, TOML for Gemini, plain prompts for Codex) and swaps the
argument token. The behavior you get is identical no matter which tool you run.
Autonomy levels
Start every new loop at L1 (report-only) - the maker proposes, never edits. Move to L2 (assisted edits, still gated) once you trust it, then L3 (unattended) only for low-risk, proven loops. The human gate defaults on.
L1 is enforced, not just promised (Claude Code only)
Everywhere above, "L1: the maker does not edit files" is an instruction in the
prompt. If you installed loopAI as a native Claude Code plugin, it is also a
hook: hooks/l1-guard.js runs on every Write, Edit, and NotebookEdit
call and checks .loops/.phase-lock.json, a small file the maker/checker
orchestrator writes before each phase. It denies the call outright when the
lock says checker (checkers never edit, at any autonomy level) or maker
with autonomy L1. A stale lock (older than 20 minutes, e.g. a crashed
session) is ignored, so a dead loop can never permanently block edits in your
repo.
How strong the guarantee is depends on which command set the lock:
loopai run(headless): bulletproof.bin/loopai.jsis real code, it writes and clears the lock itself, no model cooperation involved.engineer-agents: very strong. The orchestrating session's only job around each phase is "write the lock, then dispatch the subagent", a simple instruction to get right.engineer: strong, but the same session sets its own lock before switching into maker mode, so it is not adversarial-proof, just far better than an instruction the maker has to remember for an entire round.
This is a Claude Code plugin feature. Gemini CLI, Codex, and Cursor still rely on the prompt instruction alone, since none of them have an equivalent hook system today.
Develop locally
git clone https://github.com/javaidnaik/loopAI
cd loopAI
node bin/loopai.js install --tool all # try it without installing globallyDistribution: one repo, one branch
All commands live in prompts/ (the source of truth). Everything else is
generated from them by npm run build.
This repo is, at the same time, a Claude Code plugin. The generated
.claude-plugin/ and commands/loop/*.md are committed at the root, so Claude
users install straight from GitHub. Every other tool installs through the npm
CLI, which converts the same prompts at install time.
Claude Code (native, from this repo):
/plugin marketplace add javaidnaik/loopAI
/plugin install loopai@javaid-loopsPlugin commands are namespaced by both the plugin name and the commands/loop/
folder they live in, so every command is invoked with the full loopai:loop:
prefix: /loopai:loop:init, /loopai:loop:grill, /loopai:loop:engineer <slug>,
/loopai:loop:compass, /loopai:loop:baton, /loopai:loop:harvest,
/loopai:loop:guard, plus /loopai:loop:engineer-agents <slug> for real
subagent isolation (see below). Run /help after installing to see the full
list. This is longer than the /loop:init style shown above for the
CLI-installed version, because that one writes plain project commands instead
of a plugin.
If a plugin install ever reports a command as missing right after you add the
marketplace, run /plugin marketplace update javaid-loops to refresh the
listing before trying /plugin install again.
Gemini CLI, Codex CLI, Cursor (via the CLI):
npm install -g @javaidnaik/loopai
loopai install --tool gemini # or codex, cursor, claude, allAdd or edit a command once in prompts/, run npm run build, commit, and every
channel updates together. npm run build also emits dist/gemini, dist/codex,
and dist/cursor (gitignored) if you ever want to publish a native package for
one of those in its own repo, but you do not need to.
This mirrors how mattpocock/skills ships: one repo, source files plus a Claude plugin manifest, and an installer that adapts to other agents.
Note: Google has said the free Gemini CLI is being folded into Antigravity CLI, so confirm the current Gemini install path on their docs before relying on it.
Credits
Several commands are adapted and generalized from mattpocock/skills (MIT): the grilling interview, the handoff doc, PRD/issue output, and git guardrails. His are per-session engineering skills. loopAI reworks the ideas into portable commands that run identically across Claude Code, Gemini CLI, Codex, and Cursor.
Structure
loopAI/
bin/loopai.js the installer, and the local run/stats/cron/doctor CLI
prompts/
init.md canonical init logic
grill.md canonical interview logic
engineer.md canonical loop (maker + checker, one session)
agents/
maker.md Claude Code subagent: does the work
checker.md Claude Code subagent: strict read-only verifier
commands/loop/
engineer-agents.md Claude Code only: engineer, dispatched to real subagents
hooks/
hooks.json registers l1-guard.js on Write/Edit/NotebookEdit
l1-guard.js enforces .loops/.phase-lock.json, Claude Code only
package.json npm bin: loopaiMIT
