@taurgis/bonsai
v3.2.0
Published
Bonsai is a standalone local research cache CLI for AI agents
Downloads
1,411
Readme
Bonsai
Bonsai is a standalone local research cache CLI for AI agents. It turns official documentation and web pages into source-cited Markdown artifacts, stores them in a durable local cache, and returns deterministic output that agents can reuse instead of repeatedly scraping the same pages.
The package is published as @taurgis/bonsai and installs a bonsai binary.
📚 Full documentation: bonsai.rhino-inquisitor.com
Because the npm package is scoped, the correct one-shot command is
npx @taurgis/bonsai .... The unscopednpx bonsainame resolves to the separatebonsaipackage on npm unless an unscoped shim is published later.
What it Does
| Feature | How it works | Typical use case |
| --- | --- | --- |
| Scrape and convert | Fetches HTML, extracts main content, sanitizes unsafe markup, and converts it to deterministic Markdown | Capturing API docs, guides, standards, and changelogs |
| Cache-first lookup | Normalizes URLs to collision-resistant SHA-256 keys before fetching | Avoiding duplicate network requests and repeated agent research |
| Token budgeting | Returns compressed or detailed Markdown variants | Fitting research into limited context windows without losing full detail |
| Freshness tiers | Supports stable, standard, volatile, custom TTLs, and stale revalidation | Handling standards differently from release notes or beta docs |
| Browser fallback | Uses --rendered for pages that need client-side JavaScript | Capturing SPA documentation when static HTML is incomplete |
| Manual import | Stores agent-supplied Markdown from stdin or files | Caching synthesized notes, private docs, or manually extracted pages |
| List | Filters cached entries by topic, tags, freshness, and metadata | Seeing what is already cached without reading full content |
Installation
Requires Node.js 22 or newer.
Run Bonsai without installing it globally:
npx @taurgis/bonsai https://nodejs.org/api/url.htmlInstall it as a normal CLI:
npm install -g @taurgis/bonsai
bonsai https://nodejs.org/api/url.htmlUse the local development binary inside this repository:
pnpm install
pnpm build
node bin/cli.mjs --helpQuick Start
1. Fetch and cache a URL
npx @taurgis/bonsai https://nodejs.org/api/url.htmlThe first run fetches the page, extracts the main article content, converts it to Markdown, estimates token size, and stores it locally.
2. Reuse the cache
npx @taurgis/bonsai https://nodejs.org/api/url.htmlThe second run returns from cache when the entry is still fresh.
3. Check cache state and metadata
npx @taurgis/bonsai status https://nodejs.org/api/url.html
npx @taurgis/bonsai inspect https://nodejs.org/api/url.html4. Import manual research notes
echo "# My Custom Node API Notes" | npx @taurgis/bonsai import https://nodejs.org/api/url.html --stdin
echo "# Synthesized React Cache Guide" | npx @taurgis/bonsai import --stdin --topic "React Suspense" --source-url https://react.dev/a --source-url https://react.dev/b5. List cached entries
npx @taurgis/bonsai list --tags nodeCommand Reference
<url>
Fetch and format a webpage, or retrieve it from cache.
npx @taurgis/bonsai <url> [flags]Common flags:
--topic,-t: Primary category/topic for metadata tagging.--tags,-g: Searchable tags. Can be repeated. When omitted, tags are auto-generated from the content by keyword detection (recorded with anauto-generated tags via keyword extractionquality note); passing--tagsalways takes precedence.--format,-f: Output density:compressedordetailed.--tier: Freshness tier:stable,standard, orvolatile.--ttl,-l: Custom predicted lifespan, such as2h,7d, or30d.--max-age: Read-time freshness threshold.--force: Force a fresh fetch.--dry-run: Scrape and validate without writing to cache.--allow-stale: Serve stale cache if the remote site is offline.--rendered: Use browser-rendered extraction for SPA pages.--read-only(alias--plan): Block all filesystem writes/deletes across every command; network fetches still run. See Read-only / plan mode below.--json: Return structured machine-readable output.
import [url]
Save custom Markdown notes directly to the cache. As with fetch, when --tags is omitted the tags are auto-generated from the note content by keyword detection.
npx @taurgis/bonsai import [url] --stdin [flags]status <url>
Inspect cache state and planned action without fetching.
npx @taurgis/bonsai status <url> [flags]inspect <url>
Display stored YAML frontmatter metadata for a URL.
npx @taurgis/bonsai inspect <url>list
List cached artifacts by metadata filters (--topic, --tags, --freshness, --artifact-type, --capture-method, --limit), newest first, without printing content.
npx @taurgis/bonsai list [flags]prune
Delete old or inactive cache entries. Requires a filter (--older-than, --inactive, --artifact-type, or --url) and exactly one of --dry-run or --yes (passing both is a usage error). In read-only mode, --yes is rejected and the safety check is implicitly satisfied by a preview.
npx @taurgis/bonsai prune --older-than 90d --dry-runconfig
Two keys are configurable:
| Key | Values | Default | Effect |
| --- | --- | --- | --- |
| storage | global, project | global | Where cache files are stored. |
| summary | conservative, balanced, aggressive | conservative | How aggressively the compressed format is shortened when structural compression alone leaves it close to detailed. Prose is condensed extractively (no LLM); headings, code blocks, tables, and lists are always preserved. |
npx @taurgis/bonsai config set storage project --local
npx @taurgis/bonsai config set summary balancedBoth keys can also be overridden per-invocation via the BONSAI_STORAGE and BONSAI_SUMMARY environment variables. Project config is stored in .bonsai.json; project cache files are stored under .bonsai/research/.
Read-only / plan mode
Every command accepts a global --read-only flag (alias --plan) that blocks all filesystem writes and deletes — cache persistence, config file writes, prune deletions — while still allowing network fetches to run. This is for agent harnesses (Claude Code and others) that enter a read-only "plan mode": set it once and every bonsai invocation for the rest of that session automatically skips writes, without needing the flag on every call.
BONSAI_READ_ONLY=1 npx @taurgis/bonsai https://example.com/docs
npx @taurgis/bonsai import https://example.com/docs --file notes.md --read-only
npx @taurgis/bonsai prune --older-than 90d --planIt can also be set via the BONSAI_READ_ONLY or BONSAI_PLAN_MODE environment variables (both are equivalent). Composition is OR, not override: read-only mode is active if either env var or the flag is set, and there is no way to force writes back on once one of them is — this is a safety gate, not a preference. Commands that already expose --dry-run (fetch, prune, config set/unset) treat it the same as an explicit --dry-run; import (which has no --dry-run of its own) previews the write and reports dryRun: true instead of persisting.
Shell Autocomplete
Bonsai ships with shell autocomplete via @oclif/plugin-autocomplete. After installing globally, set it up once for your shell:
# Bash — add to ~/.bashrc
eval "$(bonsai autocomplete bash)"
# Zsh — add to ~/.zshrc
eval "$(bonsai autocomplete zsh)"
# Fish
bonsai autocomplete fish > ~/.config/fish/completions/bonsai.fishTo see full setup instructions including the copy-paste snippet for your shell:
bonsai autocompleteRefresh cached completions after upgrading:
bonsai autocomplete --refresh-cacheFreshness and Cache Rules
Global cache files live in Bonsai's oclif data directory, typically:
- macOS:
~/Library/Application Support/bonsai/research/ - Linux:
~/.local/share/bonsai/research/ - Windows:
%LOCALAPPDATA%\bonsai\research\
Project-local storage uses:
.bonsai.jsonfor the project config.bonsai/research/for Markdown cache artifacts
If no --ttl is specified, freshness is computed from the tier:
| Tier | Fresh duration | Grace window | Use case |
| --- | --- | --- | --- |
| volatile | 7 days | 5 days | Latest releases, volatile changelogs, beta docs |
| standard | 30 days | 14 days | General API docs and developer guides |
| stable | 180 days | 60 days | RFCs, standards, long-lived references |
When stale entries still have ETag or Last-Modified metadata, Bonsai attempts cheap revalidation before a full refetch. If revalidation fails and --allow-stale is omitted, the CLI can serve the stale content while exiting with code 5.
JSON Envelope
When run with --json, commands return a stable envelope:
{
"schemaVersion": 1,
"command": "bonsai",
"ok": true,
"exitCode": 0,
"stdout": "",
"stderr": "",
"data": {
"schemaVersion": 1,
"command": "bonsai",
"cache": {
"key": "0f115db062b7c0dd030b16878c99dea5c354b49dc37b38eb8846179c7783e9d7",
"status": "hit",
"freshness": "fresh",
"path": "/Users/user/Library/Application Support/bonsai/research/0f115db062b7c0dd030b16878c99dea5c354b49dc37b38eb8846179c7783e9d7.md"
},
"source": {
"url": "https://example.com",
"normalizedUrl": "https://example.com/",
"captureMethod": "static_fetch",
"extractionStatus": "extracted",
"extractionConfidence": "low",
"qualityNotes": ["readability extracted main article"],
"fetchedAt": "2026-06-24T07:33:20.519Z",
"validatedAt": "2026-06-24T07:33:20.519Z",
"staleAfter": "2026-07-24T07:33:20.519Z"
},
"format": "compressed",
"tokenEstimate": 29,
"content": "Cleaned main content markdown text..."
}
}Environment Variables
| Variable | Effect |
| --- | --- |
| BONSAI_STORAGE | Override the default storage location per-invocation (global or project). |
| BONSAI_SUMMARY | Override the summary compression level per-invocation (conservative, balanced, or aggressive). |
| BONSAI_READ_ONLY / BONSAI_PLAN_MODE | Set to 1/true/yes to enable read-only/plan mode for every command in the session, equivalent to passing --read-only (--plan) each time. Either variable is sufficient; there is no way to override it back off from a single invocation. |
| NO_COLOR | Set to any non-empty value to disable all ANSI color output. An empty NO_COLOR is treated as unset. |
| FORCE_COLOR | Set to any value other than an empty string, 0, or false to force ANSI color on, even in non-TTY environments. |
| TERM=dumb | Disables ANSI color output when the terminal cannot render escape sequences. |
| NO_UPDATE_NOTIFIER | Suppress the "update available" notification. |
| CI | Set to 1 or true to suppress the update notification in CI environments (detected automatically). |
| DEBUG | Enable debug output for specific Bonsai namespaces, e.g. DEBUG=bonsai:*. |
Exit Codes
| Code | Meaning |
| --- | --- |
| 0 | Success. |
| 1 | Runtime failure (network error, fetch failed, file read error). |
| 2 | Usage error (invalid flag, bad URL, missing required argument). |
| 5 | Stale content served — the cache entry is past its grace window but --allow-stale is set. The returned content is still usable. |
Security and Limits
- Fetched HTML is treated as untrusted input.
- Only
http:andhttps:URLs are accepted. - Private and local IP ranges are blocked to reduce SSRF risk.
- Static extraction does not execute JavaScript; use
--renderedwhen a page needs browser execution. - Authenticated/private scraping is not supported in the default workflow. Import trusted Markdown manually instead.
Reference Documentation
The full documentation site lives at
bonsai.rhino-inquisitor.com (built with
VitePress from the docs/ folder). Key pages:
