@taurgis/bonsai 4.0.0 → 4.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.
Files changed (61) hide show
  1. package/README.md +24 -1
  2. package/agents/agents/official-docs-researcher.agent.md +102 -0
  3. package/agents/agents/salesforce-docs-researcher.agent.md +16 -14
  4. package/agents/hooks/README.md +18 -2
  5. package/agents/hooks/claude-code/hooks/bonsai-web-fetch.sh +1 -1
  6. package/agents/hooks/codex/hooks/bonsai-user-prompt-context.sh +1 -1
  7. package/agents/hooks/codex/hooks/bonsai-web-fetch.sh +1 -1
  8. package/agents/hooks/cursor/hooks/bonsai-web-fetch.sh +1 -1
  9. package/agents/hooks/github-copilot/bonsai-web-fetch.sh +1 -1
  10. package/agents/instructions/salesforce-research.instructions.md +5 -4
  11. package/agents/instructions/web-research.instructions.md +45 -0
  12. package/agents/skills/web-research/SKILL.md +139 -0
  13. package/dist/base-command.d.ts +5 -0
  14. package/dist/base-command.js +9 -0
  15. package/dist/commands/config/base.d.ts +2 -7
  16. package/dist/commands/config/base.js +4 -18
  17. package/dist/commands/context.d.ts +20 -0
  18. package/dist/commands/context.js +65 -0
  19. package/dist/commands/list.d.ts +12 -3
  20. package/dist/commands/list.js +61 -100
  21. package/dist/commands/search.d.ts +43 -0
  22. package/dist/commands/search.js +233 -0
  23. package/dist/commands/setup.d.ts +27 -0
  24. package/dist/commands/setup.js +148 -0
  25. package/dist/commands.d.ts +6 -0
  26. package/dist/commands.js +6 -0
  27. package/dist/lib/argv.js +4 -1
  28. package/dist/lib/cli-presentation.d.ts +19 -0
  29. package/dist/lib/cli-presentation.js +27 -0
  30. package/dist/lib/cli-result-types.d.ts +59 -0
  31. package/dist/lib/color.d.ts +2 -0
  32. package/dist/lib/color.js +6 -0
  33. package/dist/lib/common-metadata-filter-flags.d.ts +14 -0
  34. package/dist/lib/common-metadata-filter-flags.js +37 -0
  35. package/dist/lib/next-command.d.ts +15 -0
  36. package/dist/lib/next-command.js +40 -0
  37. package/dist/lib/research/context-dashboard.d.ts +19 -0
  38. package/dist/lib/research/context-dashboard.js +43 -0
  39. package/dist/lib/research/fetch-command-service.js +10 -0
  40. package/dist/lib/research/fetch-result.d.ts +1 -0
  41. package/dist/lib/research/fetch-result.js +4 -0
  42. package/dist/lib/research/list-row.d.ts +15 -0
  43. package/dist/lib/research/list-row.js +31 -0
  44. package/dist/lib/research/metadata-filters.d.ts +22 -1
  45. package/dist/lib/research/metadata-filters.js +34 -0
  46. package/dist/lib/research/schema.d.ts +2 -0
  47. package/dist/lib/research/schema.js +4 -0
  48. package/dist/lib/research/search-match.d.ts +39 -0
  49. package/dist/lib/research/search-match.js +134 -0
  50. package/dist/lib/scope-flags.d.ts +19 -0
  51. package/dist/lib/scope-flags.js +27 -0
  52. package/dist/lib/setup/agents.d.ts +16 -0
  53. package/dist/lib/setup/agents.js +20 -0
  54. package/dist/lib/setup/bin-command.d.ts +14 -0
  55. package/dist/lib/setup/bin-command.js +42 -0
  56. package/dist/lib/setup/hook-file-io.d.ts +37 -0
  57. package/dist/lib/setup/hook-file-io.js +80 -0
  58. package/dist/lib/text.d.ts +6 -0
  59. package/dist/lib/text.js +11 -0
  60. package/oclif.manifest.json +288 -3
  61. package/package.json +1 -1
package/README.md CHANGED
@@ -21,6 +21,7 @@ The package is published as `@taurgis/bonsai` and installs a `bonsai` binary.
21
21
  | **Browser fallback** | Uses `--rendered` for pages that need client-side JavaScript | Capturing SPA documentation when static HTML is incomplete |
22
22
  | **Manual import** | Stores agent-supplied Markdown from stdin or files | Caching synthesized notes, private docs, or manually extracted pages |
23
23
  | **List** | Filters cached entries by topic, tags, freshness, and metadata | Seeing what is already cached without reading full content |
24
+ | **Search** | Ranks cached entries by keyword across tags, summary, and compressed content | Finding what's already cached on a topic without an exact topic/tag match |
24
25
 
25
26
  ---
26
27
 
@@ -88,6 +89,12 @@ echo "# Synthesized React Cache Guide" | npx @taurgis/bonsai import --stdin --to
88
89
  npx @taurgis/bonsai list --tags node
89
90
  ```
90
91
 
92
+ ### 6. Search cached entries by keyword
93
+
94
+ ```bash
95
+ npx @taurgis/bonsai search --query "url parsing"
96
+ ```
97
+
91
98
  ---
92
99
 
93
100
  ## Command Reference
@@ -141,12 +148,28 @@ npx @taurgis/bonsai inspect <url>
141
148
 
142
149
  ### `list`
143
150
 
144
- List cached artifacts by metadata filters (`--topic`, `--tags`, `--url`, `--freshness`, `--artifact-type`, `--capture-method`, `--limit`), newest first, without printing content. The default `--json`/`--toon` row is a minimal 4-field shape (`sourceUrls`, `topic`, `freshness`, `tokenEstimate`); pass `--full` for every metadata field. Running `bonsai` with no arguments at all is shorthand for `bonsai list`.
151
+ List cached artifacts by metadata filters (`--topic`, `--tags`, `--url`, `--freshness`, `--artifact-type`, `--capture-method`, `--limit`), newest first, without printing content. The default `--json`/`--toon` row is a minimal 4-field shape (`sourceUrls`, `topic`, `freshness`, `tokenEstimate`); pass `--full` for every metadata field. `--limit` defaults to 10 so an unfiltered call never floods the caller's context; a truncated result's `summary.nextCommand` gives a ready-to-run command with `--limit` raised. Running `bonsai` with no arguments at all is shorthand for `bonsai list`, preceded by a `bin:`/`description:` identity header (human mode only, that bare invocation only).
145
152
 
146
153
  ```bash
147
154
  npx @taurgis/bonsai list [flags]
148
155
  ```
149
156
 
157
+ ### `search`
158
+
159
+ Rank cached artifacts by keyword — the content/tag search `list` doesn't do. `--query` matches
160
+ (case-insensitive) against topic, tags, `summary`, and `compressed` content; every term must match
161
+ somewhere unless `--match-any` is set. Every other filter (`--topic`, `--tags`, `--url`,
162
+ `--freshness`, `--artifact-type`, `--capture-method`) works exactly like `list`'s. Each row adds a
163
+ relevance `score`, which fields matched (`matchedFields`), and a short excerpt around the first
164
+ content match (`snippet`) — reading only the token-cheap indexed `summary`/`compressed` text, never
165
+ the full `detailed` body, so ranking a large cache stays fast and never balloons context. Omitting
166
+ `--query` behaves like `list`: every row scores `0`, sorted newest-first. `--limit` defaults to 10,
167
+ same as `list`.
168
+
169
+ ```bash
170
+ npx @taurgis/bonsai search --query "suspense boundary" --tags react
171
+ ```
172
+
150
173
  ### `prune`
151
174
 
152
175
  Delete old or inactive cache entries. Requires a filter (`--older-than`, `--inactive`, `--artifact-type`, `--url`, `--topic`, or `--tags`) and exactly one of `--dry-run` or `--yes` (passing both is a usage error). In [read-only mode](#read-only--plan-mode), `--yes` is rejected and the safety check is implicitly satisfied by a preview.
@@ -0,0 +1,102 @@
1
+ ---
2
+ name: 'Official Docs Researcher'
3
+ description: 'Researches official documentation through Bonsai and returns source-cited findings'
4
+ model: 'Auto'
5
+ tools: ['vscode/askQuestions', 'execute', 'read', 'search', 'web', 'vscode/memory']
6
+ argument-hint: 'What topic should I research in official docs?'
7
+ metadata:
8
+ version: '4.5.0'
9
+ ---
10
+
11
+ # Official Docs Researcher Agent
12
+
13
+ You are a Forward documentation research specialist. Your job is to find current official documentation, cache it through Bonsai, and return concise source-cited findings that another agent can apply safely.
14
+
15
+ ## Scope
16
+
17
+ Use this agent for technical changes, platform behavior, APIs, SDKs, standards, release notes, changelogs, beta docs, security advisories, and other documentation-sensitive work.
18
+
19
+ Do not research from memory alone. Training-data knowledge does not satisfy this workflow.
20
+
21
+ ## Invocation
22
+
23
+ Run Bonsai as `npx @taurgis/bonsai ...`. Default to `--toon` for structured output — the same envelope as `--json`, at a lower token cost — as every example below does. Reach for `--json` only when a caller specifically needs real JSON (mutually exclusive with `--toon`).
24
+
25
+ If you are operating in a read-only/plan mode (no filesystem writes allowed), add `--read-only` (alias `--plan`) to every Bonsai call, or export `BONSAI_READ_ONLY=1` (or `BONSAI_PLAN_MODE=1`) once for the session — fetches still run, but nothing is persisted to the local cache or config. See "Read-only / Plan Mode" below.
26
+
27
+ ## Default Workflow
28
+
29
+ 1. Identify the product, version, edition, and source authority needed for the request.
30
+ 2. Check whether relevant research is already cached before starting new fetches:
31
+
32
+ ```bash
33
+ npx @taurgis/bonsai search --query "<topic keywords>" --toon
34
+ ```
35
+
36
+ A hit still needs a freshness check (see below) before you trust it as current.
37
+ 3. Locate official source URLs for anything not already cached. Prefer vendor docs, standards bodies, API references, and official release notes. Use your native web/search tools when you do not yet know the URL.
38
+ 4. Capture each source through Bonsai:
39
+
40
+ ```bash
41
+ npx @taurgis/bonsai <official-url> --format detailed --toon
42
+ ```
43
+
44
+ 5. Use `--rendered` for SPAs or pages where static extraction is incomplete:
45
+
46
+ ```bash
47
+ npx @taurgis/bonsai <official-url> --rendered --format detailed --toon
48
+ ```
49
+
50
+ 6. Summarize only what the official sources support. Include source URLs, validation time when available, version notes, and any important limitations.
51
+
52
+ ## Freshness Policy
53
+
54
+ Choose the freshness tier based on the source:
55
+
56
+ - `stable`: standards, specs, MDN reference pages, pinned major-version docs.
57
+ - `standard`: vendor API docs, SDK docs, normal technical references.
58
+ - `volatile`: release notes, changelogs, latest pages, security advisories, beta docs.
59
+
60
+ Stale volatile sources must be revalidated before they are trusted. Never overwrite a good cache entry with an error response.
61
+
62
+ ## Read-only / Plan Mode
63
+
64
+ Bonsai supports a global `--read-only` flag (alias `--plan`), also honored via the `BONSAI_READ_ONLY`/`BONSAI_PLAN_MODE` environment variables, that blocks all filesystem writes and deletes (cache persistence, config writes, `prune` deletions) while still allowing network fetches to run. Use it whenever you are invoked under a read-only/plan-mode harness so this research workflow stays non-destructive:
65
+
66
+ - Research fetches (`npx @taurgis/bonsai <url>`) still hit the network and return content normally; they just skip writing the result to the local cache.
67
+ - `import` previews the write and reports `dryRun: true` instead of persisting.
68
+ - `config set` / `config unset` preview the write and report `would_set` / `would_unset`.
69
+ - `prune` treats `--read-only` like an implicit dry run; combining it with `--yes` is rejected.
70
+
71
+ Composition is OR: once read-only mode is active (flag or either env var), there is no per-call way to force writes back on.
72
+
73
+ ## Fallbacks
74
+
75
+ If direct web access was unavoidable because Bonsai could not fetch the content, import the synthesized notes back into Bonsai before returning:
76
+
77
+ ```bash
78
+ npx @taurgis/bonsai import <url> --file <path> --toon
79
+ ```
80
+
81
+ For multi-source synthesis:
82
+
83
+ ```bash
84
+ npx @taurgis/bonsai import \
85
+ --topic "<descriptive topic>" \
86
+ --source-url <url1> \
87
+ --source-url <url2> \
88
+ --file <path> \
89
+ --toon
90
+ ```
91
+
92
+ ## Response Contract
93
+
94
+ Return:
95
+
96
+ - Answer summary.
97
+ - Official source URLs used.
98
+ - Version, edition, or date constraints.
99
+ - Cache status or validation timestamp when Bonsai output provides it.
100
+ - Gaps or uncertainty where official docs do not answer the question.
101
+
102
+ Keep stdout clean when using `--toon`/`--json`; warnings and diagnostic notes belong in stderr or in the final prose summary.
@@ -5,7 +5,7 @@ model: 'Auto'
5
5
  tools: ['vscode/askQuestions', 'execute', 'read', 'search', 'web', 'vscode/memory']
6
6
  argument-hint: 'What Salesforce topic should I research in official docs?'
7
7
  metadata:
8
- version: '2.2.0'
8
+ version: '2.5.0'
9
9
  ---
10
10
 
11
11
  # Salesforce Docs Researcher Agent
@@ -20,33 +20,34 @@ Do not research from memory alone. Training-data knowledge does not satisfy this
20
20
 
21
21
  ## Invocation
22
22
 
23
- Run Bonsai as `npx @taurgis/bonsai ...`. Add `--toon` when you need structured output at a lower token cost; `--json` is also available if you specifically need JSON (mutually exclusive with `--toon`).
23
+ Run Bonsai as `npx @taurgis/bonsai ...`. Default to `--toon` for structured output — the same envelope as `--json`, at a lower token cost — as every example below does. Reach for `--json` only when a caller specifically needs real JSON (mutually exclusive with `--toon`).
24
24
 
25
25
  If you are operating in a read-only/plan mode (no filesystem writes allowed), add `--read-only` (alias `--plan`) to every Bonsai call, or export `BONSAI_READ_ONLY=1` (or `BONSAI_PLAN_MODE=1`) once for the session — fetches still run, but nothing is persisted to the local cache or config. See "Read-only / Plan Mode" below.
26
26
 
27
27
  ## Default Workflow
28
28
 
29
29
  1. Identify the product, version, edition, and source authority needed for the request.
30
- 2. Locate official Salesforce source URLs. Use your native web/search tools when you do not yet know the URL.
31
- 3. Capture each source through Bonsai:
30
+ 2. Check whether relevant research is already cached before starting new fetches:
32
31
 
33
32
  ```bash
34
- npx @taurgis/bonsai <official-url> --format detailed
33
+ npx @taurgis/bonsai search --query "<topic keywords>" --toon
35
34
  ```
36
35
 
37
- 4. Use `--rendered` for SPAs or pages where static extraction is incomplete:
36
+ A hit still needs a freshness check (see below) before you trust it as current.
37
+ 3. Locate official Salesforce source URLs for anything not already cached. Use your native web/search tools when you do not yet know the URL.
38
+ 4. Capture each source through Bonsai:
38
39
 
39
40
  ```bash
40
- npx @taurgis/bonsai <official-url> --rendered --format detailed
41
+ npx @taurgis/bonsai <official-url> --format detailed --toon
41
42
  ```
42
43
 
43
- 5. Summarize only what the official sources support. Include source URLs, validation time when available, version notes, and any important limitations.
44
+ 5. Use `--rendered` for SPAs or pages where static extraction is incomplete:
44
45
 
45
- For structured output:
46
+ ```bash
47
+ npx @taurgis/bonsai <official-url> --rendered --format detailed --toon
48
+ ```
46
49
 
47
- ```bash
48
- npx @taurgis/bonsai <official-url> --format detailed --toon
49
- ```
50
+ 6. Summarize only what the official sources support. Include source URLs, validation time when available, version notes, and any important limitations.
50
51
 
51
52
  ## Working with Salesforce Sites
52
53
 
@@ -86,7 +87,7 @@ Composition is OR: once read-only mode is active (flag or either env var), there
86
87
  If direct web access was unavoidable because Bonsai could not fetch the content, import the synthesized notes back into Bonsai before returning:
87
88
 
88
89
  ```bash
89
- npx @taurgis/bonsai import <url> --file <path>
90
+ npx @taurgis/bonsai import <url> --file <path> --toon
90
91
  ```
91
92
 
92
93
  For multi-source synthesis:
@@ -96,7 +97,8 @@ npx @taurgis/bonsai import \
96
97
  --topic "<descriptive topic>" \
97
98
  --source-url <url1> \
98
99
  --source-url <url2> \
99
- --file <path>
100
+ --file <path> \
101
+ --toon
100
102
  ```
101
103
 
102
104
  ## Response Contract
@@ -7,12 +7,28 @@ They are examples, not an installer contract. Copy the relevant folder contents
7
7
  into the agent's native hook location and adjust paths if your repository layout
8
8
  differs.
9
9
 
10
+ ## Ambient session context (`bonsai setup`)
11
+
12
+ The examples below only cover the *redirect-away-from-web-fetch* half of hook
13
+ integration. For the complementary half — showing an agent the cache's current
14
+ state before it does anything — run `bonsai setup <agent>` instead of copying
15
+ files by hand. It installs (and repairs) a `SessionStart` hook that runs
16
+ `bonsai context` at the start of every session, supporting `claude-code` and
17
+ `codex` today. See [Ambient session
18
+ context](https://bonsai.rhino-inquisitor.com/how-to/agent-integration#ambient-session-context)
19
+ for the full workflow.
20
+
21
+ OpenCode is not supported by `setup` yet: its plugin docs don't document a
22
+ confirmed hook signature for injecting session-start context (closest is
23
+ `session.created`, unconfirmed shape), so `setup` won't guess at one rather than
24
+ ship an integration that might not work.
25
+
10
26
  ## What The Hooks Do
11
27
 
12
28
  The hooks deny native URL-fetch tools and return model-visible guidance like:
13
29
 
14
30
  ```bash
15
- npx @taurgis/bonsai https://example.com/docs --format detailed
31
+ npx @taurgis/bonsai https://example.com/docs --format detailed --toon
16
32
  ```
17
33
 
18
34
  Most hook systems cannot transparently replace a web-fetch tool call with a shell
@@ -51,5 +67,5 @@ that tells the agent to prefer Bonsai for URLs.
51
67
  Run Bonsai through the published npm package:
52
68
 
53
69
  ```bash
54
- npx @taurgis/bonsai <url> --format detailed
70
+ npx @taurgis/bonsai <url> --format detailed --toon
55
71
  ```
@@ -9,7 +9,7 @@ const input = JSON.parse(fs.readFileSync(0, "utf8") || "{}");
9
9
  const raw = JSON.stringify(input.tool_input ?? input);
10
10
  const match = raw.match(/https?:\/\/[^\s"'\''<>)}\]]+/);
11
11
  const url = match ? match[0] : "<url>";
12
- const command = `npx @taurgis/bonsai ${url} --format detailed`;
12
+ const command = `npx @taurgis/bonsai ${url} --format detailed --toon`;
13
13
  const reason =
14
14
  `Use Bonsai instead of the native web fetch so the result is cached and reusable. Run: ${command}`;
15
15
  process.stdout.write(JSON.stringify({
@@ -12,7 +12,7 @@ process.stdout.write(JSON.stringify({
12
12
  hookSpecificOutput: {
13
13
  hookEventName: "UserPromptSubmit",
14
14
  additionalContext:
15
- "When fetching documentation or URL content for this prompt, use Bonsai first: npx @taurgis/bonsai <url> --format detailed. Use --rendered only when static extraction is incomplete."
15
+ "When fetching documentation or URL content for this prompt, use Bonsai first: npx @taurgis/bonsai <url> --format detailed --toon. Use --rendered only when static extraction is incomplete."
16
16
  }
17
17
  }) + "\n");
18
18
  ' <<< "$input"
@@ -9,7 +9,7 @@ const input = JSON.parse(fs.readFileSync(0, "utf8") || "{}");
9
9
  const raw = JSON.stringify(input.tool_input ?? input);
10
10
  const match = raw.match(/https?:\/\/[^\s"'\''<>)}\]]+/);
11
11
  const url = match ? match[0] : "<url>";
12
- const command = `npx @taurgis/bonsai ${url} --format detailed`;
12
+ const command = `npx @taurgis/bonsai ${url} --format detailed --toon`;
13
13
  const reason =
14
14
  `Use Bonsai instead of this URL-fetch tool so the result is cached and reusable. Run: ${command}`;
15
15
  process.stdout.write(JSON.stringify({
@@ -9,7 +9,7 @@ const input = JSON.parse(fs.readFileSync(0, "utf8") || "{}");
9
9
  const raw = JSON.stringify(input.tool_input ?? input.toolArgs ?? input);
10
10
  const match = raw.match(/https?:\/\/[^\s"'\''<>)}\]]+/);
11
11
  const url = match ? match[0] : "<url>";
12
- const command = `npx @taurgis/bonsai ${url} --format detailed`;
12
+ const command = `npx @taurgis/bonsai ${url} --format detailed --toon`;
13
13
  const message =
14
14
  `Use Bonsai instead of the native URL fetch so the result is cached and reusable. Run: ${command}`;
15
15
  process.stdout.write(JSON.stringify({
@@ -9,7 +9,7 @@ const input = JSON.parse(fs.readFileSync(0, "utf8") || "{}");
9
9
  const raw = JSON.stringify(input.toolArgs ?? input.tool_input ?? input);
10
10
  const match = raw.match(/https?:\/\/[^\s"'\''<>)}\]]+/);
11
11
  const url = match ? match[0] : "<url>";
12
- const command = `npx @taurgis/bonsai ${url} --format detailed`;
12
+ const command = `npx @taurgis/bonsai ${url} --format detailed --toon`;
13
13
  const reason =
14
14
  `Use Bonsai instead of web_fetch so the result is cached and reusable. Run: ${command}`;
15
15
  process.stdout.write(JSON.stringify({
@@ -4,7 +4,7 @@ applyTo: '**'
4
4
  skills:
5
5
  - web-research
6
6
  metadata:
7
- version: '2.1.0'
7
+ version: '2.4.0'
8
8
  ---
9
9
 
10
10
  # Web Research Requirement (Salesforce)
@@ -24,9 +24,10 @@ metadata:
24
24
 
25
25
  ## Shared Cache
26
26
 
27
- - **Invocation**: Run Bonsai as `npx @taurgis/bonsai ...`.
27
+ - **Invocation**: Run Bonsai as `npx @taurgis/bonsai ...`. Default to `--toon` for structured output (same envelope as `--json`, fewer tokens); use `--json` only when a caller specifically needs real JSON.
28
28
  - **URL discovery**: When you do not yet know the official URL, discover it with your native web/search tools, then fetch the page through Bonsai so it is cached for future agents.
29
- - **Browse cached entries**: Use `npx @taurgis/bonsai list` when you need to see what is already cached by topic, tags, or freshness.
29
+ - **Browse cached entries**: Use `npx @taurgis/bonsai list --toon` when you need to see what is already cached by topic, tags, or freshness. Prefer `--toon` over `--json` for lower token cost.
30
+ - **Search cached entries**: Use `npx @taurgis/bonsai search --query "<keywords>" --toon` when you don't know the exact topic/tag to filter on — it ranks cached entries by a query matched against topic, tags, and page content. Both commands default `--limit` to 10; a truncated result's `summary.nextCommand` gives you the exact command to raise it.
30
31
  - If Bonsai is configured for project storage and `.bonsai/research/` is not ignored by git, treat those cache artifacts as intentional shared project files. It is OK to check them in, and agents must not delete them as incidental generated output without an explicit request.
31
32
  - Re-running on a recent topic is cheap — research the topic rather than skipping it to "save" a fetch.
32
33
  - If you are operating under a read-only/plan-mode harness, add `--read-only` (alias `--plan`) to Bonsai calls, or rely on `BONSAI_READ_ONLY`/`BONSAI_PLAN_MODE` if the harness sets it — fetches still run, but nothing is persisted to the local cache or config; `config set` / `config unset` preview with `would_set` / `would_unset`.
@@ -38,7 +39,7 @@ Salesforce Help and Developer docs are JavaScript-rendered (LWR), so Bonsai uses
38
39
  - **Help and Developer fetch.** Once you have a URL, capture it through Bonsai:
39
40
 
40
41
  ```bash
41
- npx @taurgis/bonsai <official-url> --format detailed
42
+ npx @taurgis/bonsai <official-url> --format detailed --toon
42
43
  ```
43
44
 
44
45
  - Matching is by exact hostname; prefer canonical `/s/articleView?id=…` Help URLs (Bonsai normalizes legacy `/help_doccontent?id=…` links automatically).
@@ -0,0 +1,45 @@
1
+ ---
2
+ description: 'Verify current official docs before technical repo changes — inline via the web-research skill for minor research, via the Official Docs Researcher subagent for extensive research.'
3
+ applyTo: '**'
4
+ skills:
5
+ - web-research
6
+ metadata:
7
+ version: '4.2.0'
8
+ ---
9
+
10
+ # Web Research Requirement
11
+
12
+ ## Mandatory Pre-Step
13
+
14
+ - Verify the relevant current official documentation **in the same task** before creating, updating, refactoring, scaffolding, or deleting technical content.
15
+ - Apply what you find — cite official source URLs when the change relies on platform behavior or standards.
16
+ - Research is the requirement; how you run it scales with scope (below). Training-data knowledge never satisfies this — only docs fetched in the current task do.
17
+
18
+ ## Choose How to Research by Scope
19
+
20
+ - **Minor research — run it inline.** For a single known page, one platform, or a quick flag/API/version check, the main agent invokes the **web-research** skill directly. A separate subagent is not required.
21
+ - **Extensive research — delegate to a subagent.** For multiple sources or platforms, unfamiliar territory, broad audits, or anything that produces verbose output you do not want in the main context, run the **Official Docs Researcher** subagent and apply its findings.
22
+ - The main agent may always use the **web-research** skill directly — choose the subagent to isolate large research, not because inline research is disallowed.
23
+ - When unsure, start inline and escalate to the subagent once the work spans several sources.
24
+
25
+ ## Shared Cache
26
+
27
+ - **Invocation**: Run Bonsai as `npx @taurgis/bonsai ...`. Default to `--toon` for structured output (same envelope as `--json`, fewer tokens); use `--json` only when a caller specifically needs real JSON.
28
+ - **URL discovery**: When you do not yet know the official URL, discover it with your native web/search tools, then fetch the page through Bonsai so it is cached for future agents.
29
+ - If Bonsai is configured for project storage and `.bonsai/research/` is not ignored by git, treat those cache artifacts as intentional shared project files. It is OK to check them in, and agents must not delete them as incidental generated output without an explicit request.
30
+ - Re-running on a recent topic is cheap — research the topic rather than skipping it to "save" a fetch.
31
+ - If you are operating under a read-only/plan-mode harness, add `--read-only` (alias `--plan`) to Bonsai calls, or rely on `BONSAI_READ_ONLY`/`BONSAI_PLAN_MODE` if the harness sets it — fetches still run, but nothing is persisted to the local cache or config; `config set` / `config unset` preview with `would_set` / `would_unset`.
32
+
33
+ ## When Not to Use
34
+
35
+ - No technical content is being modified (purely editorial changes).
36
+ - You already fetched and applied official docs **in the current task**. Training-data knowledge does not satisfy this — only docs fetched in the same task do.
37
+ - The request is too simple to warrant research (typo, lint fix not involving platform behavior).
38
+
39
+ ## Examples
40
+
41
+ - ✅ Confirming one platform's current flag or frontmatter field before a small edit → run the web-research skill inline.
42
+ - ✅ Comparing conventions across several platforms, or auditing/refactoring source broadly → delegate to the Official Docs Researcher subagent.
43
+ - ✅ Before editing instructions, prompts, agents, skills, workflows, or docs — reading source code does not replace checking current platform guidance.
44
+ - ✅ Include official source URLs when the change references platform behavior or standards.
45
+ - ❌ Don't modify technical content without researching first, and don't treat cached or training knowledge as equivalent — official guidance evolves and must be verified per task.
@@ -0,0 +1,139 @@
1
+ ---
2
+ name: web-research
3
+ description: 'Bonsai-backed official documentation and web research workflow. Use before technical changes that depend on platform behavior, when fetching documentation or web pages, when listing/searching/pruning the local research cache, or when importing manually gathered notes.'
4
+ license: Forward Proprietary
5
+ compatibility: VS Code 1.x+, GitHub Copilot
6
+ metadata:
7
+ version: '3.5.0'
8
+ ---
9
+
10
+ # Web Research Skill
11
+
12
+ Use Bonsai as the cache-first research path for official documentation and web content. Prefer current official sources, keep research reusable, and avoid direct one-off web fetches when Bonsai can capture the same page.
13
+
14
+ ## Invocation
15
+
16
+ Always run Bonsai through the published npm package:
17
+
18
+ ```bash
19
+ npx @taurgis/bonsai <command> [flags]
20
+ ```
21
+
22
+ Default to `--toon` for structured output — the same envelope as `--json`, at a lower token cost — as every example below does. Reach for `--json` only when a caller specifically needs real JSON (mutually exclusive with `--toon`).
23
+
24
+ If you are operating under a read-only/plan-mode harness, add `--read-only` (alias `--plan`) to every Bonsai call, or export `BONSAI_READ_ONLY=1` (or `BONSAI_PLAN_MODE=1`) once for the session. Fetches still run and return content normally; nothing is written to the local cache or config until the harness leaves plan mode. `import`, `config set`/`unset`, and `prune` all honor it too — see "Read-only / Plan Mode" below.
25
+
26
+ ## Required Pre-Step
27
+
28
+ Before creating, updating, refactoring, scaffolding, or deleting technical content, verify relevant current official documentation in the same task.
29
+
30
+ When you do not yet know the official URL, discover it with your native web/search tools first. Once you have a URL, capture it through Bonsai:
31
+
32
+ ```bash
33
+ npx @taurgis/bonsai <official-url> --format detailed --toon
34
+ ```
35
+
36
+ ## Source Rules
37
+
38
+ - Prefer official vendor docs, standards, API references, SDK docs, release notes, changelogs, and security advisories.
39
+ - Include official source URLs when the change relies on platform behavior or standards.
40
+ - Use `--tier stable`, `--tier standard`, or `--tier volatile` when the source class is clear.
41
+ - Treat volatile sources as needing fresh validation before trusting them.
42
+ - Do not use the retired manual `artifacts/online-research/` protocol for new research.
43
+
44
+ ## Fetch Rules
45
+
46
+ Use `--format compressed` for context-budgeted reading and `--format detailed` for exact technical details, links, tables, and code examples.
47
+
48
+ Use `--rendered` when static extraction is incomplete or the page is an SPA:
49
+
50
+ ```bash
51
+ npx @taurgis/bonsai <official-url> --rendered --format detailed --toon
52
+ ```
53
+
54
+ Never reach for direct `WebFetch` or `WebSearch` to retrieve a specific page when Bonsai can fetch it. Bonsai returns reusable Markdown and keeps it cached for future agents.
55
+
56
+ ## Manual Fallbacks
57
+
58
+ If direct web access was unavoidable because of authentication, browser interaction, or a tool constraint, import the result into Bonsai before returning.
59
+
60
+ Single-source import:
61
+
62
+ ```bash
63
+ npx @taurgis/bonsai import <url> --file path/to/notes.md --toon
64
+ ```
65
+
66
+ Stdin import:
67
+
68
+ ```bash
69
+ echo "# My Synthesis Note" | npx @taurgis/bonsai import <url> --stdin --toon
70
+ ```
71
+
72
+ Multi-source synthesis:
73
+
74
+ ```bash
75
+ npx @taurgis/bonsai import \
76
+ --topic "<descriptive topic>" \
77
+ --source-url <url1> \
78
+ --source-url <url2> \
79
+ --file path/to/synthesized-notes.md \
80
+ --toon
81
+ ```
82
+
83
+ ## Cache Operations
84
+
85
+ Check status without fetching:
86
+
87
+ ```bash
88
+ npx @taurgis/bonsai status <url> --toon
89
+ ```
90
+
91
+ Inspect stored metadata:
92
+
93
+ ```bash
94
+ npx @taurgis/bonsai inspect <url> --toon
95
+ ```
96
+
97
+ List cached entries by metadata. Prefer `--toon` for agent callers — same data as `--json`, fewer
98
+ tokens:
99
+
100
+ ```bash
101
+ npx @taurgis/bonsai list --tags node --toon
102
+ ```
103
+
104
+ Search cached entries by tag or content keyword when you don't know the exact topic/tag to filter
105
+ on — ranks page-level entries by a query matched against topic, tags, summary, and compressed
106
+ content:
107
+
108
+ ```bash
109
+ npx @taurgis/bonsai search --query "suspense boundary" --toon
110
+ ```
111
+
112
+ Both default `--limit` to 10 so a broad query never floods your context. A truncated result's
113
+ envelope carries `summary.truncated` and `summary.nextCommand` — a ready-to-run command that
114
+ reproduces your filters with a raised `--limit` — so raise it deliberately only when you actually
115
+ need more, instead of requesting a large `--limit` up front.
116
+
117
+ Preview pruning before deleting:
118
+
119
+ ```bash
120
+ npx @taurgis/bonsai prune --older-than 90d --dry-run --toon
121
+ npx @taurgis/bonsai prune --older-than 90d --yes --toon
122
+ ```
123
+
124
+ ## Read-only / Plan Mode
125
+
126
+ Bonsai supports a global `--read-only` flag (alias `--plan`), also honored via the `BONSAI_READ_ONLY`/`BONSAI_PLAN_MODE` environment variables, that blocks all filesystem writes and deletes (cache persistence, config writes, `prune` deletions) while still allowing network fetches to run:
127
+
128
+ - Research fetches still hit the network and return content normally; they just skip writing the result to the local cache.
129
+ - `import` previews the write and reports `dryRun: true` instead of persisting.
130
+ - `prune` treats `--read-only` like an implicit dry run; combining it with `--yes` is rejected.
131
+
132
+ Composition is OR: once read-only mode is active (flag or either env var), there is no per-call way to force writes back on. Use this whenever the calling agent itself is confined to a read-only/plan mode, so research stays possible without violating that constraint.
133
+
134
+ ## When This Does Not Apply
135
+
136
+ - No technical content or web content is involved.
137
+ - You already fetched and applied current official docs in the current task.
138
+ - The request is a trivial typo or formatting fix that does not involve platform behavior.
139
+ - `npx @taurgis/bonsai` is unavailable in the environment; use the best available official-source workflow and import notes later.
@@ -66,6 +66,11 @@ export declare abstract class BaseCommand<T extends typeof Command> extends Comm
66
66
  * `data` is self-describing, so machine callers get no prose.
67
67
  */
68
68
  protected tip(message: string): void;
69
+ /**
70
+ * Human-mode tip for a truncated `list`/`search` result: the copy-pasteable command that raises
71
+ * `--limit` (see `next-command.ts`). A no-op when nothing was truncated (`nextCommand` is `null`).
72
+ */
73
+ protected tipNextCommand(nextCommand: string | null): void;
69
74
  /** Whether read-only/plan mode is active for this invocation (flag OR either env var). */
70
75
  protected get readOnly(): boolean;
71
76
  /**
@@ -2,6 +2,7 @@ import { Command, Errors, Flags, toConfiguredId, ux } from '@oclif/core';
2
2
  import { encode } from '@toon-format/toon';
3
3
  import { invalidConfigFileWarnings, invalidEnvOverrideWarnings, resolveReadOnly, } from './lib/config/index.js';
4
4
  import { CLI_FLAG_DESCRIPTIONS } from './lib/cli-presentation.js';
5
+ import { colors } from './lib/color.js';
5
6
  import { formatTip, sanitizeForTerminal } from './lib/text.js';
6
7
  import { enrichErrorForDisplay, resolveExitCode, prepareCliError, EXIT_OK, EXIT_STALE_SERVED, } from './lib/cli-error-policy.js';
7
8
  import { buildEnvelope, enrichCacheMissEnvelope, enrichRowErrorEnvelope } from './lib/envelope.js';
@@ -145,6 +146,14 @@ export class BaseCommand extends Command {
145
146
  return;
146
147
  this.warn(formatTip(message));
147
148
  }
149
+ /**
150
+ * Human-mode tip for a truncated `list`/`search` result: the copy-pasteable command that raises
151
+ * `--limit` (see `next-command.ts`). A no-op when nothing was truncated (`nextCommand` is `null`).
152
+ */
153
+ tipNextCommand(nextCommand) {
154
+ if (nextCommand)
155
+ this.tip(`see the rest: ${colors.cyan(nextCommand)}`);
156
+ }
148
157
  /** Whether read-only/plan mode is active for this invocation (flag OR either env var). */
149
158
  get readOnly() {
150
159
  return resolveReadOnly({ flag: Boolean(this.flags?.['read-only']), env: process.env });
@@ -1,6 +1,7 @@
1
1
  import { Command } from '@oclif/core';
2
2
  import { BaseCommand } from '../../base-command.js';
3
3
  import type { ConfigKey, ConfigScope } from '../../lib/config/index.js';
4
+ import { scopeFlags } from '../../lib/scope-flags.js';
4
5
  /**
5
6
  * Shared base for the four `config` subcommands: the mutually-exclusive
6
7
  * scope-flag guard, the binary write-scope helper, and known-key validation.
@@ -16,10 +17,4 @@ export declare abstract class ConfigCommand<T extends typeof Command> extends Ba
16
17
  protected validateConfigKeyAndScope(key: string | undefined, global?: boolean, local?: boolean): asserts key is ConfigKey;
17
18
  }
18
19
  /** Build the `--global`/`--local` scope-flag pair with per-command descriptions. */
19
- export declare function configScopeFlags(descriptions: {
20
- global: string;
21
- local: string;
22
- }): {
23
- global: import("@oclif/core/interfaces").BooleanFlag<boolean>;
24
- local: import("@oclif/core/interfaces").BooleanFlag<boolean>;
25
- };
20
+ export declare const configScopeFlags: typeof scopeFlags;
@@ -1,19 +1,14 @@
1
- import { Flags, toConfiguredId } from '@oclif/core';
1
+ import { toConfiguredId } from '@oclif/core';
2
2
  import { BaseCommand } from '../../base-command.js';
3
3
  import { isKnownKey, suggestKey, validKeysHint } from '../../lib/config/index.js';
4
+ import { assertScopeFlagsExclusive, scopeFlags } from '../../lib/scope-flags.js';
4
5
  /**
5
6
  * Shared base for the four `config` subcommands: the mutually-exclusive
6
7
  * scope-flag guard, the binary write-scope helper, and known-key validation.
7
8
  */
8
9
  export class ConfigCommand extends BaseCommand {
9
10
  assertScopeFlagsExclusive(global, local) {
10
- if (global && local) {
11
- this.error('--global and --local are mutually exclusive.', {
12
- exit: 2,
13
- code: 'CONFLICTING_FLAGS',
14
- suggestions: ['Pass --global or --local, not both.'],
15
- });
16
- }
11
+ assertScopeFlagsExclusive(this.error.bind(this), global, local);
17
12
  }
18
13
  /** `--local` writes/reads the project file; otherwise the user-level file. */
19
14
  writeScope(local) {
@@ -58,13 +53,4 @@ export class ConfigCommand extends BaseCommand {
58
53
  }
59
54
  }
60
55
  /** Build the `--global`/`--local` scope-flag pair with per-command descriptions. */
61
- export function configScopeFlags(descriptions) {
62
- return {
63
- global: Flags.boolean({ char: 'g', description: descriptions.global }),
64
- local: Flags.boolean({
65
- description: descriptions.local,
66
- aliases: ['project'],
67
- charAliases: ['p'],
68
- }),
69
- };
70
- }
56
+ export const configScopeFlags = scopeFlags;
@@ -0,0 +1,20 @@
1
+ import { BaseCommand } from '../base-command.js';
2
+ import type { ContextDashboard } from '../lib/cli-result-types.js';
3
+ /**
4
+ * Compact, directory-scoped cache summary (AXI principle 7: ambient session-start context).
5
+ * Plain-text human output is deliberately short — it's meant to be piped verbatim into a
6
+ * SessionStart hook's `additionalContext` by `bonsai setup`, so every line here is also a
7
+ * reasonable thing for an agent to read unprompted at the start of a session.
8
+ */
9
+ export default class Context extends BaseCommand<typeof Context> {
10
+ static id: string;
11
+ static summary: string;
12
+ static description: string;
13
+ static examples: {
14
+ description: string;
15
+ command: string;
16
+ }[];
17
+ static stdoutIsPrimaryData: boolean;
18
+ private logDashboard;
19
+ run(): Promise<ContextDashboard>;
20
+ }