Skip to content

ferdinandobons/bonsai

Repository files navigation

Bonsai

Bonsai: from the active approach to the proactive approach

Claude answers what you ask. Bonsai catches what you miss.

Bonsai is a Claude Code plugin that acts as a patient gardener for your code. After each turn of your session it silently observes what just happened and, only when it finds something that truly matters, leaves you a single observation: a latent bug you missed, a risky architectural decision you made without noticing, a workflow friction quietly costing you an hour a day.

It never touches your code. It runs in the background, independent of your session, and stays quiet most of the time. It speaks only when the signal is high. Silence beats noise is its hard rule, and the reason it's worth leaving on.

The proof

The first time the gardener ran on a real session (the transcript of building Bonsai itself), it caught two real bugs in its own codebase that sixteen rounds of code review during the build had missed:

  1. bonsai_branches_write was the only non-atomic file write in a codebase that uses atomic patterns everywhere else. The gardener writes its own observations through that function. It surfaced the bug while writing its own report about it.
  2. The CI workflow never triggered on release tags. That is exactly why two earlier releases shipped with a Linux compatibility regression.

Both fixed in v0.1.4. Both marked "kept" in the project's observation index. The loop closed in a single afternoon.

This is what proactive looks like.

Why you want it

Claude is reactive by design. You ask, Claude answers, then Claude waits. The cost of that wait is invisible until you ship: the race condition you would have caught on Monday morning ships on Friday night. The architecture decision you made in a 3am haze becomes a six-month refactor. The small repetition in your workflow becomes a daily tax.

Bonsai closes the gap between the moment something matters and the moment you notice. You stop relying on remembering to ask. The observer remembers for you.

Requirements

Bonsai is pure bash, so it runs anywhere Claude Code runs a bash hook.

  • macOS and Linux: supported natively.
  • Windows: supported via WSL2 (recommended), or Git Bash with bash 5+. Git for Windows ships bash and the GNU coreutils Bonsai needs, but not jq, so install jq separately. Line endings must stay LF: the repo's .gitattributes handles this regardless of your core.autocrlf setting.
  • Native Windows (cmd.exe / PowerShell without bash): not supported. The Stop hook is invoked with bash, so a bash runtime has to be on the path.

Install

Inside Claude Code:

/plugin marketplace add ferdinandobons/bonsai
/plugin install bonsai@bonsai

Downloaded and enabled immediately. No restart needed.

Or: edit ~/.claude/settings.json manually
{
  "extraKnownMarketplaces": {
    "bonsai": {
      "source": { "source": "github", "repo": "ferdinandobons/bonsai" }
    }
  },
  "enabledPlugins": {
    "bonsai@bonsai": true
  }
}

Restart Claude Code or run /plugin to reload.

Activate on a project

cd ~/your-project
/bonsai:start

That is the entire setup. Bonsai now watches this project silently. The interval adapts to activity: at least 5 minutes between checks when your code changed, and 20 minutes on idle/conversational turns (configurable via throttle_min_minutes / throttle_idle_minutes). Most checks produce zero observations, by design.

Commands

Watch

Command Action
/bonsai:start Start watching this project. Accepts --throttle=Xm, --lenses=a,b,c, --model=name.
/bonsai:stop Stop watching (history preserved)
/bonsai:mute <30m|1h|4h|1d> Silence temporarily. Append --global for all projects.
/bonsai:unmute Resume after a mute. Append --global to also clear a global mute.

Read

Command Action
/bonsai:status Health, quota, cost
/bonsai:list [N=5] Read the N most recent open observations
/bonsai:discuss <id> Talk through an observation in this session

Triage

Command Action
/bonsai:done <id> Mark as resolved / accepted
/bonsai:dismiss <id> [reason] Mark as not useful. The gardener learns.

Config

Command Action
/bonsai:config [key value] View current config, or set one key
/bonsai:help Full command reference

Notable keys (set with /bonsai:config <key> <value>, or as flags on /bonsai:start): gardener_model, throttle_min_minutes / throttle_idle_minutes, lenses_enabled, history_window_days (longitudinal churn window, default 7), and critical_reminder_ttl_days (stop surfacing an open critical in the reminder box after N days, default 0 = off). Set history_enabled to false in config.json to turn the churn summary off entirely.

How it works

After each turn of Claude Code, a Stop hook script runs. It clears five gates in order: whitelist (is this project watched?), mute (silenced by you?), throttle (enough time since the last check?), quota (under the daily cap, per-project and global?), and a per-project lock (no other gardener already running?). If any gate fails, it exits silently with no effect on your session.

If all gates pass, the hook:

  1. Slices the session transcript to the last 200 lines (configurable via transcript_tail_lines) so the gardener gets a bounded input regardless of how long the session is.
  2. Spawns claude -p --agent bonsai:gardener as a fully detached subprocess (nohup … & disown) and returns empty output. The gardener runs independently of the parent session. Your turn ends immediately.

The gardener then, in its own headless context:

  1. Reads the git diff and the sliced transcript, the files changed since its last run, plus a deterministic per-module git-churn summary so it can notice activity that recurs across sessions (e.g. a module touched in many recent commits).
  2. Picks one of three lenses: technical (bug patterns, security risks, performance smells, test gaps), strategic (architectural decision points, scope creep, unanswered questions), workflow (repeated steps that should be automated, missing slash commands).
  3. Drafts candidate observations against a hard quality bar, then filters them: it drops anything it already surfaced (a rolling hash window) or a theme you previously dismissed (the anti-pattern log).
  4. Runs the survivors past a cheap second model (Haiku) that catches semantic duplicates the hash check misses and calibrates each observation's severity.
  5. Writes between zero and three survivors to .claude/bonsai/branches/<id>-<slug>.md, each with full frontmatter and a self-contained action brief. Zero is the most common correct answer.
  6. Regenerates .claude/bonsai/INDEX.md so new observations show up in /bonsai:list and your editor immediately, then archives stale branches and rotates its own logs.

Observations live as readable markdown files inside each project. Commit them to git if you want a team-shared journal, or gitignore them if you want them private. Your choice, project by project.

The return reminder

Reading is pull, not push: you read observations when you choose to, with /bonsai:list. But to keep a critical finding from sitting unseen, Bonsai surfaces a soft reminder when you come back to a watched project, on the next prompt you send or when a new conversation starts. It's a small in-chat box with the top findings:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🌿 Bonsai · 2 critical observations awaiting review
  1. 2026-05-29-005 · Race condition in cache update under …
  2. 2026-05-29-003 · Unvalidated path in plugin loader
  → /bonsai:list to read · /bonsai:discuss <id> to dig in
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Only critical observations trigger it (silence still beats noise), it shows once per session, and a muted project stays silent. Reading the finding is always your move. The reminder just points.

The box keeps itself current: if the file a critical points at has since changed, that critical is automatically demoted out of the box (it moves to a needs re-check group in INDEX.md) but stays in /bonsai:list. Nothing is ever auto-deleted: an open critical you have not addressed is demoted, never lost.

Each gardener run is capped at 25 iterations and runs on the model you configure: Sonnet by default, changeable with /bonsai:config gardener_model <name> or --model on /bonsai:start. It uses your Agent SDK credit (included with Claude Pro/Max/Team/Enterprise plans); token usage per project, per day, is visible via /bonsai:status.

Uninstall

Inside Claude Code:

/plugin uninstall bonsai@bonsai
/plugin marketplace remove bonsai

This removes the marketplace clone, cache, and settings entries. Your per-project observation logs (.claude/bonsai/ inside each project) are preserved. Delete them by hand if you want a clean slate.

Privacy

Bonsai processes:

  • Your Claude Code session transcript: the Stop hook slices it to the last ~200 lines and the gardener reads that slice.
  • Files in your project (and the git diff HEAD, excluding .claude/bonsai/) to gather evidence.
  • Optional read-only git commands when a .git/ directory exists.

The gardener subagent runs through the LLM you have configured in Claude Code. No data leaves your machine beyond what your normal Claude Code usage already sends to your model provider.

Bonsai writes only inside ${CLAUDE_PROJECT_DIR}/.claude/bonsai/ and ${CLAUDE_PLUGIN_DATA}/. It never modifies your project source files.

Trust posture

  • Read-only on your code, always. The gardener has no Edit tool.
  • Silent failure. Every error path exits 0. Bonsai never disturbs a session, even when broken. Errors are written to ${CLAUDE_PLUGIN_DATA}/logs/bonsai-errors.log.
  • File system is the source of truth. The return reminder only points at findings; the markdown log under .claude/bonsai/ is the record, and it always wins.

License

Apache 2.0. See LICENSE.

Contributing

Issues and PRs welcome. See CONTRIBUTING.md. Run cd plugins/bonsai && bats tests/unit tests/integration before submitting.

Security

See SECURITY.md for the threat model and how to report vulnerabilities responsibly.

Changelog

See CHANGELOG.md. Latest: v0.7.0.

About

A patient gardener for your code — proactive observations for Claude Code.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages