kapadias/nonna

Your AI agent says done. Nonna makes it prove it: she runs your test suite before a coding agent can stop, and blocks pushes to main and secrets in files. Claude Code plugin, plus git hooks for Codex, Cursor, Copilot, Gemini and more

Shell

0

400 commits

updated Oct 1, 2026

See the code

See what people are saying

SourceMessageScoreDate

[Nonna] - makes AI coding agents pass your tests before they can say "done" (r/SideProject)

Side project I've been working on for sometime. Coding agents kept telling me a fix was done after running one test file, so I built hooks that run the whole suite when the agent tries to stop and send it back if anything fails. It also keeps the agent off main and keeps secrets out of files. Free…

1

Oct 1, 2026

README

English · 简体中文 · 한국어 · 日本語 · Español

Nonna, the grandmother with a wooden spoon: she doesn't care that it compiled.

Your AI agent says "done". Nonna makes it prove it.

Latest release Gate tests Works with Claude Code, Codex, Cursor, Copilot, Gemini and more MIT

1 of 64 runs cut a corner (bare agent: 24) · 1 of 8 said "done" on a red suite (bare: 4) · 0 of 8 pushed to main (bare: 8) · +$0.03 per change

Claude Sonnet 5.5 and Haiku 4.5, 8 trap tasks × 4 runs each, hidden checks, the plugin in lite mode. Method and raw rows · reproduce

Agents say "done" when one test file passes and another is broken. Nonna runs your whole test suite before the agent is allowed to stop, and sends it back when the suite is red. She also stops commits and pushes to main, force pushes, and secrets written into files. No model decides any of it: your test command's exit code does.

Install

In Claude Code:

/plugin marketplace add kapadias/nonna
/plugin install nonna@nonna

Or from a terminal: claude plugin marketplace add kapadias/nonna && claude plugin install nonna@nonna

Start a session in any git repository. Nonna finds your test command and tells you what she will run:

Nonna is on here (lite). Before the agent can say done, Nonna runs: python3 -m pytest -q. Added .git/hooks/pre-push and pre-commit. See or change it with /nonna.

/nonna shows what she enforces and where each setting comes from; /nonna off turns her off in this repository. Using Codex, Cursor, Copilot, Gemini or another agent? See other agents.

What she checks

WhenWhat she doesShe blocks when
The agent tries to end its turn after changing codeRuns your test commandIt exits non-zero
The agent changed code and no testAsks "where's the test?"Once; a plain reason why none is needed is accepted
The agent runs git commit or git pushBranch guardCommit or push to main, master or develop; any force push; skipping the git hooks
The agent writes, reads or searches files, or runs a commandSecret guardThe content looks like a key; it reads .env, keys or credentials
Anyone runs git pushpre-push hookRed suite, or a secret in any pushed commit
Anyone runs git commitpre-commit hookOn main, master or develop, or a staged secret

She runs your suite only when code changed, and not again on a tree that already passed. At the end of a turn she blocks once; if the agent still cannot fix it, her message tells it to say plainly that it is not done.

Modes. lite, the default, is the table above plus six short house rules. full adds a docs/STATUS.md gate and the full rules: plan first, test first, review sized by risk, and a feature → develop → main flow. Her agents and workflows (/nonna:plan, /nonna:review, /nonna:ship and more) are there in both modes, and run only when you ask. In the benchmark, full mode was no safer than lite, so treat it as extras for teams. Switch with /nonna full.

Before / after

Same prompt, same model (Claude Haiku). The obvious fix to div_cents() breaks a test in another file.

bare agent                                   nonna lite
──────────                                   ──────────
fixes div_cents()                            fixes div_cents() and split.py
"Done. Fixed `div_cents()` to round half     tries to stop: the suite is green
 up ... All 3 tests now pass ..."            ✗ Nonna: where's the test? (stop: code
                                               changed, no test changed)
the hidden check runs the whole suite:       "... My change to `split.py` removes the
  FAILED tests/test_split.py::test_odd_…      dependency on `div_cents()` ... allowing
  2 failed, 7 passed                          both the money tests and split tests to
                                              pass ..."
                                             the hidden check: 9 passed

Both columns quote round 3's runs, picked by a rule and not by how they read: the full pages. Without Nonna, 4 of 8 runs of this task (prompt, hidden check) ended with a broken suite and a "done". With Nonna lite, 1 of 8.

What Nonna says

WhenShe says
Tests are red at the end of a turn✗ Nonna: you said done; the tests say no.
Code changed and no test did✗ Nonna: where's the test?
Commit on main✗ Nonna: not in my kitchen, tesoro. Make a branch.
Push to main✗ Nonna: nobody pushes to main in my house. Open a PR.
Force push✗ Nonna: we don't force things in this house.
A key in a file✗ Nonna: you don't leave the house key under the mat.
Reading .env✗ Nonna: that drawer is private.

Each line is followed by the technical reason, so the agent knows what to fix.

The numbers

Nonna lite versus a bare agent. Cut a corner on 8 trap tasks, Claude Sonnet + Haiku, 4 runs each: bare agent 24 of 64 runs, nonna lite 1 of 64. Said done on a broken test suite: 4 of 8 versus 1 of 8. Pushed to main when told to push: 8 of 8 versus 0 of 8. Cost per change, Claude Sonnet: trap tasks $0.04 versus $0.06, small feature tasks $0.04 versus $0.07.

Bare agentNonna liteNonna full
Cut a corner, 8 trap tasks, Sonnet + Haiku24 / 641 / 640 / 64
Said "done" on a red suite (task)4 / 81 / 80 / 8
Pushed to main when asked to "commit and push" (task)8 / 80 / 80 / 8
Left a regression test (task)0 / 88 / 88 / 8
Cost per small feature, Sonnet, same prompt$0.040$0.071$0.096
Time per small feature, Sonnet12 s20 s24 s

Each trap task is an ordinary request that makes a shortcut tempting. A hidden check scores the result; the agent never sees it. 1 of 64 still allows a true rate of up to about 8% (Wilson 95%). On six tickets in a real repository (full-stack-fastapi-template), lite kept the bare agent's pass rate (30 of 36 against 28) and was no safer (1 unsafe run against 1): those traps break what the repository's own tests don't check, and she runs the tests there are.

What went wrong, in the open: lite's one miss passed its own suite but not the original tests, so the agent had changed the tests or their setup, which no gate checks yet; and without Nonna, Claude Sonnet no longer leaves this red suite behind, so the second row is Haiku's. Method, per-task tables, raw rows and every caveat: bench/. One run of each trap, word for word: examples/.

Reproduce

git clone https://github.com/kapadias/nonna && cd nonna
bash bench/verify/verify.sh      # proves the checkers, no API calls
bash bench/run.sh --suite traps --arm none,plugin-lite --model sonnet --reps 4

About $3 on Sonnet, billed to ANTHROPIC_API_KEY. The rules these numbers were read by were registered before the run.

Works with ponytail, caveman and superpowers

caveman makes the agent say less. ponytail makes it build less. superpowers teaches it a method. Nonna checks what it did.

Other agents

From the root of a git repository:

curl -fsSL https://raw.githubusercontent.com/kapadias/nonna/main/install.sh | bash

For another agent, add -s -- --host <name>:

Agent--host
Claude Codeclaude (default)
Codex, Zed, Amp, opencode, Roo Code, Jules, Junie (AGENTS.md)agents
Cursorcursor
GitHub Copilotcopilot
Gemini CLIgemini · or the extension
Windsurf · Cline · Kirowindsurf · cline · kiro
all of themall

install.sh installs lite: the gates, the git hooks, /nonna and the house rules. Add --mode full for the whole harness: the full rules, agents, workflows and docs/STATUS.md. Running it again keeps the mode a repository already has.

Codex can also take her as a plugin, which adds her hooks: run codex plugin marketplace add kapadias/nonna, install Nonna from /plugins, and trust her hooks in /hooks (docs/INSTALL.md).

GitHub Copilot CLI also takes her as a plugin, which runs her gates in the agent's own hooks:

copilot plugin marketplace add kapadias/nonna
copilot plugin install nonna@nonna

What each agent gets:

Claude CodeCodex (plugin)Copilot CLI (plugin)Every other agent
Nonna's house rulesyesyesyesyes
Git hooks: no commit on main, no staged secretyesyesyesyes
Git hooks: no push with red tests or a secretyesyesyesyes
Can't end its turn on a red suite; "where's the test?"yeswired¹wired²no³
Secret guard on every file write and read, branch guard on every commandyeswired¹wired²no³

¹ The same scripts, run on Codex's events and tested against the hook payloads Codex documents. They have not yet run in a Codex session end to end, and the benchmark has no Codex arm, so nothing here says they do for Codex what they do for Claude Code. Codex reads files through the shell, where the secret guard checks what a command reads. They do not see input sent to a shell already running, or scan what the shell writes; the git hooks are the backstop there (docs/INSTALL.md).

² Through Copilot's sessionStart, preToolUse and agentStop hooks, which Copilot CLI documents for plugins (1.0.72 or later). Golden-tested against Copilot's documented hook payloads; not yet run in a live Copilot session. An apply_patch is judged a file at a time, as Codex's is. docs/INSTALL.md says what differs.

³ Copilot CLI also runs the hooks install.sh writes into .claude/settings.json, untranslated: they read its commands but not its file tools, and beside the plugin each gate runs twice. With Copilot, use the plugin.

From Nonna v2.0.0, Gemini CLI can also load the house rules as an extension: gemini extensions install https://github.com/kapadias/nonna. It carries the rules only, with no git hooks; install.sh --host gemini adds them (details).

Nothing you already have is overwritten. More: docs/INSTALL.md.

FAQ

Is it just a prompt? No. A prompt cannot refuse a push. The gates are shell scripts that run your test command and read git; the rules only make them fire less often. In the benchmark, lite's agents mostly followed the rules, so her hardest gates rarely had to fire. They are there for the run that doesn't.

How is it different from superpowers or tdd-guard? superpowers gives the agent skills that tell it to verify its work; nothing stops the turn if it doesn't. tdd-guard asks a model whether each edit follows TDD. Nonna asks no model: she runs your test command and blocks on a non-zero exit, and adds branch and secret guards both in the agent and in git.

Can an agent still get past her? Yes, in two ways we have seen. She runs your tests as they are, so an agent that changes a test, or its setup, to make the suite pass gets through: lite's one miss in the benchmark did that, which her rules forbid and no gate checks yet. And she cannot see what no test checks: on the real-repository tickets, the traps that got through broke things no test there covers. She makes the checks you have unskippable; she does not add the ones you don't.

Will it slow me down? A little: in the benchmark, lite added about 8 seconds to a small feature on Sonnet. She runs the suite only when code changed, and not again for a tree that already passed. At the end of a turn, a suite slower than 240 seconds does not block; the pre-push hook still runs it in full.

What does it change on my machine? .git/hooks/pre-push and .git/hooks/pre-commit (only if you have none), a few nonna.* keys in the repository's git config, and small files under .git/ (the last green run, when the session began, which branches she has warned about). Nothing is committed. No hook makes a network call. /nonna uninstall removes all of it.

Isn't it more expensive? About 3 cents per small change on Sonnet ($0.071 against $0.040, the same prompt for both). When she pays for herself: the break-even table.

What if I need to ship without a test? On a branch, behind a debt: marker that says when you will add it. She will remember.

Windows? Use WSL 2 (or macOS or Linux). On native Windows several gates do not stop what they guard, and some never start: what was measured.

Why Nonna? Because she doesn't care that it compiled.

Uninstall

/nonna uninstall
claude plugin uninstall nonna@nonna

In that order: the first removes the git hooks and settings from the repository, the second removes the plugin.

Development

bash tests/run.sh              # every gate proven to block and to allow (1739 golden tests)
python3 tests/harness_lint.py  # word budgets, host files in sync, hook wiring, README numbers

CONTRIBUTING.md · SECURITY.md · CHANGELOG.md

Credits

The decision ladder, the debt: marker convention, the over-engineering review tags and the subagent context carrier are adapted from ponytail by Dietrich Gebert (MIT).

License

MIT © 2026 Shashank Kapadia. Short, like a good recipe.

Star History

Star History Chart
agent-guardrails
agent-skills
ai-agents
claude-code
claude-code-hooks
claude-code-plugin
codex
coding-agents
cursor
cursor-rules
developer-tools
gemini-cli
git-hooks
github-copilot
pre-commit
pre-push
secret-scanning
tdd
test-driven-development

kapadias/nonna

Your AI agent says done. Nonna makes it prove it: she runs your test suite before a coding agent can stop, and blocks pushes to main and secrets in files. Claude Code plugin, plus git hooks for Codex, Cursor, Copilot, Gemini and more

Shell

0

400 commits

updated Oct 1, 2026

See the code

See what people are saying

SourceMessageScoreDate

[Nonna] - makes AI coding agents pass your tests before they can say "done" (r/SideProject)

Side project I've been working on for sometime. Coding agents kept telling me a fix was done after running one test file, so I built hooks that run the whole suite when the agent tries to stop and send it back if anything fails. It also keeps the agent off main and keeps secrets out of files. Free…

1

Oct 1, 2026

README

English · 简体中文 · 한국어 · 日本語 · Español

Nonna, the grandmother with a wooden spoon: she doesn't care that it compiled.

Your AI agent says "done". Nonna makes it prove it.

Latest release Gate tests Works with Claude Code, Codex, Cursor, Copilot, Gemini and more MIT

1 of 64 runs cut a corner (bare agent: 24) · 1 of 8 said "done" on a red suite (bare: 4) · 0 of 8 pushed to main (bare: 8) · +$0.03 per change

Claude Sonnet 5.5 and Haiku 4.5, 8 trap tasks × 4 runs each, hidden checks, the plugin in lite mode. Method and raw rows · reproduce

Agents say "done" when one test file passes and another is broken. Nonna runs your whole test suite before the agent is allowed to stop, and sends it back when the suite is red. She also stops commits and pushes to main, force pushes, and secrets written into files. No model decides any of it: your test command's exit code does.

Install

In Claude Code:

/plugin marketplace add kapadias/nonna
/plugin install nonna@nonna

Or from a terminal: claude plugin marketplace add kapadias/nonna && claude plugin install nonna@nonna

Start a session in any git repository. Nonna finds your test command and tells you what she will run:

Nonna is on here (lite). Before the agent can say done, Nonna runs: python3 -m pytest -q. Added .git/hooks/pre-push and pre-commit. See or change it with /nonna.

/nonna shows what she enforces and where each setting comes from; /nonna off turns her off in this repository. Using Codex, Cursor, Copilot, Gemini or another agent? See other agents.

What she checks

WhenWhat she doesShe blocks when
The agent tries to end its turn after changing codeRuns your test commandIt exits non-zero
The agent changed code and no testAsks "where's the test?"Once; a plain reason why none is needed is accepted
The agent runs git commit or git pushBranch guardCommit or push to main, master or develop; any force push; skipping the git hooks
The agent writes, reads or searches files, or runs a commandSecret guardThe content looks like a key; it reads .env, keys or credentials
Anyone runs git pushpre-push hookRed suite, or a secret in any pushed commit
Anyone runs git commitpre-commit hookOn main, master or develop, or a staged secret

She runs your suite only when code changed, and not again on a tree that already passed. At the end of a turn she blocks once; if the agent still cannot fix it, her message tells it to say plainly that it is not done.

Modes. lite, the default, is the table above plus six short house rules. full adds a docs/STATUS.md gate and the full rules: plan first, test first, review sized by risk, and a feature → develop → main flow. Her agents and workflows (/nonna:plan, /nonna:review, /nonna:ship and more) are there in both modes, and run only when you ask. In the benchmark, full mode was no safer than lite, so treat it as extras for teams. Switch with /nonna full.

Before / after

Same prompt, same model (Claude Haiku). The obvious fix to div_cents() breaks a test in another file.

bare agent                                   nonna lite
──────────                                   ──────────
fixes div_cents()                            fixes div_cents() and split.py
"Done. Fixed `div_cents()` to round half     tries to stop: the suite is green
 up ... All 3 tests now pass ..."            ✗ Nonna: where's the test? (stop: code
                                               changed, no test changed)
the hidden check runs the whole suite:       "... My change to `split.py` removes the
  FAILED tests/test_split.py::test_odd_…      dependency on `div_cents()` ... allowing
  2 failed, 7 passed                          both the money tests and split tests to
                                              pass ..."
                                             the hidden check: 9 passed

Both columns quote round 3's runs, picked by a rule and not by how they read: the full pages. Without Nonna, 4 of 8 runs of this task (prompt, hidden check) ended with a broken suite and a "done". With Nonna lite, 1 of 8.

What Nonna says

WhenShe says
Tests are red at the end of a turn✗ Nonna: you said done; the tests say no.
Code changed and no test did✗ Nonna: where's the test?
Commit on main✗ Nonna: not in my kitchen, tesoro. Make a branch.
Push to main✗ Nonna: nobody pushes to main in my house. Open a PR.
Force push✗ Nonna: we don't force things in this house.
A key in a file✗ Nonna: you don't leave the house key under the mat.
Reading .env✗ Nonna: that drawer is private.

Each line is followed by the technical reason, so the agent knows what to fix.

The numbers

Nonna lite versus a bare agent. Cut a corner on 8 trap tasks, Claude Sonnet + Haiku, 4 runs each: bare agent 24 of 64 runs, nonna lite 1 of 64. Said done on a broken test suite: 4 of 8 versus 1 of 8. Pushed to main when told to push: 8 of 8 versus 0 of 8. Cost per change, Claude Sonnet: trap tasks $0.04 versus $0.06, small feature tasks $0.04 versus $0.07.

Bare agentNonna liteNonna full
Cut a corner, 8 trap tasks, Sonnet + Haiku24 / 641 / 640 / 64
Said "done" on a red suite (task)4 / 81 / 80 / 8
Pushed to main when asked to "commit and push" (task)8 / 80 / 80 / 8
Left a regression test (task)0 / 88 / 88 / 8
Cost per small feature, Sonnet, same prompt$0.040$0.071$0.096
Time per small feature, Sonnet12 s20 s24 s

Each trap task is an ordinary request that makes a shortcut tempting. A hidden check scores the result; the agent never sees it. 1 of 64 still allows a true rate of up to about 8% (Wilson 95%). On six tickets in a real repository (full-stack-fastapi-template), lite kept the bare agent's pass rate (30 of 36 against 28) and was no safer (1 unsafe run against 1): those traps break what the repository's own tests don't check, and she runs the tests there are.

What went wrong, in the open: lite's one miss passed its own suite but not the original tests, so the agent had changed the tests or their setup, which no gate checks yet; and without Nonna, Claude Sonnet no longer leaves this red suite behind, so the second row is Haiku's. Method, per-task tables, raw rows and every caveat: bench/. One run of each trap, word for word: examples/.

Reproduce

git clone https://github.com/kapadias/nonna && cd nonna
bash bench/verify/verify.sh      # proves the checkers, no API calls
bash bench/run.sh --suite traps --arm none,plugin-lite --model sonnet --reps 4

About $3 on Sonnet, billed to ANTHROPIC_API_KEY. The rules these numbers were read by were registered before the run.

Works with ponytail, caveman and superpowers

caveman makes the agent say less. ponytail makes it build less. superpowers teaches it a method. Nonna checks what it did.

Other agents

From the root of a git repository:

curl -fsSL https://raw.githubusercontent.com/kapadias/nonna/main/install.sh | bash

For another agent, add -s -- --host <name>:

Agent--host
Claude Codeclaude (default)
Codex, Zed, Amp, opencode, Roo Code, Jules, Junie (AGENTS.md)agents
Cursorcursor
GitHub Copilotcopilot
Gemini CLIgemini · or the extension
Windsurf · Cline · Kirowindsurf · cline · kiro
all of themall

install.sh installs lite: the gates, the git hooks, /nonna and the house rules. Add --mode full for the whole harness: the full rules, agents, workflows and docs/STATUS.md. Running it again keeps the mode a repository already has.

Codex can also take her as a plugin, which adds her hooks: run codex plugin marketplace add kapadias/nonna, install Nonna from /plugins, and trust her hooks in /hooks (docs/INSTALL.md).

GitHub Copilot CLI also takes her as a plugin, which runs her gates in the agent's own hooks:

copilot plugin marketplace add kapadias/nonna
copilot plugin install nonna@nonna

What each agent gets:

Claude CodeCodex (plugin)Copilot CLI (plugin)Every other agent
Nonna's house rulesyesyesyesyes
Git hooks: no commit on main, no staged secretyesyesyesyes
Git hooks: no push with red tests or a secretyesyesyesyes
Can't end its turn on a red suite; "where's the test?"yeswired¹wired²no³
Secret guard on every file write and read, branch guard on every commandyeswired¹wired²no³

¹ The same scripts, run on Codex's events and tested against the hook payloads Codex documents. They have not yet run in a Codex session end to end, and the benchmark has no Codex arm, so nothing here says they do for Codex what they do for Claude Code. Codex reads files through the shell, where the secret guard checks what a command reads. They do not see input sent to a shell already running, or scan what the shell writes; the git hooks are the backstop there (docs/INSTALL.md).

² Through Copilot's sessionStart, preToolUse and agentStop hooks, which Copilot CLI documents for plugins (1.0.72 or later). Golden-tested against Copilot's documented hook payloads; not yet run in a live Copilot session. An apply_patch is judged a file at a time, as Codex's is. docs/INSTALL.md says what differs.

³ Copilot CLI also runs the hooks install.sh writes into .claude/settings.json, untranslated: they read its commands but not its file tools, and beside the plugin each gate runs twice. With Copilot, use the plugin.

From Nonna v2.0.0, Gemini CLI can also load the house rules as an extension: gemini extensions install https://github.com/kapadias/nonna. It carries the rules only, with no git hooks; install.sh --host gemini adds them (details).

Nothing you already have is overwritten. More: docs/INSTALL.md.

FAQ

Is it just a prompt? No. A prompt cannot refuse a push. The gates are shell scripts that run your test command and read git; the rules only make them fire less often. In the benchmark, lite's agents mostly followed the rules, so her hardest gates rarely had to fire. They are there for the run that doesn't.

How is it different from superpowers or tdd-guard? superpowers gives the agent skills that tell it to verify its work; nothing stops the turn if it doesn't. tdd-guard asks a model whether each edit follows TDD. Nonna asks no model: she runs your test command and blocks on a non-zero exit, and adds branch and secret guards both in the agent and in git.

Can an agent still get past her? Yes, in two ways we have seen. She runs your tests as they are, so an agent that changes a test, or its setup, to make the suite pass gets through: lite's one miss in the benchmark did that, which her rules forbid and no gate checks yet. And she cannot see what no test checks: on the real-repository tickets, the traps that got through broke things no test there covers. She makes the checks you have unskippable; she does not add the ones you don't.

Will it slow me down? A little: in the benchmark, lite added about 8 seconds to a small feature on Sonnet. She runs the suite only when code changed, and not again for a tree that already passed. At the end of a turn, a suite slower than 240 seconds does not block; the pre-push hook still runs it in full.

What does it change on my machine? .git/hooks/pre-push and .git/hooks/pre-commit (only if you have none), a few nonna.* keys in the repository's git config, and small files under .git/ (the last green run, when the session began, which branches she has warned about). Nothing is committed. No hook makes a network call. /nonna uninstall removes all of it.

Isn't it more expensive? About 3 cents per small change on Sonnet ($0.071 against $0.040, the same prompt for both). When she pays for herself: the break-even table.

What if I need to ship without a test? On a branch, behind a debt: marker that says when you will add it. She will remember.

Windows? Use WSL 2 (or macOS or Linux). On native Windows several gates do not stop what they guard, and some never start: what was measured.

Why Nonna? Because she doesn't care that it compiled.

Uninstall

/nonna uninstall
claude plugin uninstall nonna@nonna

In that order: the first removes the git hooks and settings from the repository, the second removes the plugin.

Development

bash tests/run.sh              # every gate proven to block and to allow (1739 golden tests)
python3 tests/harness_lint.py  # word budgets, host files in sync, hook wiring, README numbers

CONTRIBUTING.md · SECURITY.md · CHANGELOG.md

Credits

The decision ladder, the debt: marker convention, the over-engineering review tags and the subagent context carrier are adapted from ponytail by Dietrich Gebert (MIT).

License

MIT © 2026 Shashank Kapadia. Short, like a good recipe.

Star History

Star History Chart
agent-guardrails
agent-skills
ai-agents
claude-code
claude-code-hooks
claude-code-plugin
codex
coding-agents
cursor
cursor-rules
developer-tools
gemini-cli
git-hooks
github-copilot
pre-commit
pre-push
secret-scanning
tdd
test-driven-development

Languages

Shell

60.2%

Python

36.5%

Awk

2.2%