@taurgis/bonsai 1.0.6 → 3.0.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 (120) hide show
  1. package/README.md +7 -13
  2. package/agents/agents/official-docs-researcher.agent.md +15 -35
  3. package/agents/agents/salesforce-docs-researcher.agent.md +17 -44
  4. package/agents/hooks/README.md +2 -9
  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 +7 -8
  11. package/agents/instructions/web-research.instructions.md +3 -4
  12. package/agents/skills/web-research/SKILL.md +24 -37
  13. package/bin/cli.mjs +15 -2
  14. package/dist/base-command.d.ts +15 -2
  15. package/dist/base-command.js +32 -4
  16. package/dist/commands/fetch.d.ts +2 -0
  17. package/dist/commands/fetch.js +43 -29
  18. package/dist/commands/import.js +11 -3
  19. package/dist/commands/inspect.d.ts +4 -0
  20. package/dist/commands/inspect.js +48 -24
  21. package/dist/commands/list.d.ts +3 -1
  22. package/dist/commands/list.js +42 -25
  23. package/dist/commands/prune.d.ts +1 -0
  24. package/dist/commands/prune.js +35 -9
  25. package/dist/commands/status.d.ts +2 -0
  26. package/dist/commands/status.js +57 -25
  27. package/dist/commands.d.ts +0 -2
  28. package/dist/commands.js +0 -2
  29. package/dist/hooks/command-not-found/suggest.d.ts +7 -1
  30. package/dist/hooks/command-not-found/suggest.js +82 -57
  31. package/dist/lib/argv.js +51 -7
  32. package/dist/lib/color.d.ts +20 -0
  33. package/dist/lib/color.js +36 -0
  34. package/dist/lib/envelope.js +8 -2
  35. package/dist/lib/help-preflight.d.ts +15 -0
  36. package/dist/lib/help-preflight.js +81 -0
  37. package/dist/lib/limit-flag.d.ts +1 -0
  38. package/dist/lib/limit-flag.js +24 -0
  39. package/dist/lib/research/{search-index.d.ts → artifact-index.d.ts} +5 -5
  40. package/dist/lib/research/{search-index.js → artifact-index.js} +10 -10
  41. package/dist/lib/research/browser.d.ts +0 -8
  42. package/dist/lib/research/browser.js +20 -43
  43. package/dist/lib/research/regression.d.ts +18 -0
  44. package/dist/lib/research/regression.js +47 -0
  45. package/dist/lib/research/storage.d.ts +0 -1
  46. package/dist/lib/research/storage.js +15 -13
  47. package/dist/lib/research/url.d.ts +22 -0
  48. package/dist/lib/research/url.js +63 -1
  49. package/dist/lib/text.d.ts +3 -1
  50. package/dist/lib/text.js +9 -1
  51. package/dist/sites/coveo.d.ts +7 -0
  52. package/dist/sites/coveo.js +33 -0
  53. package/dist/sites/index.js +1 -18
  54. package/dist/sites/salesforce/fetch-page.js +1 -1
  55. package/dist/sites/salesforce/index.js +3 -8
  56. package/dist/sites/salesforce-developer/fetch-page.js +3 -1
  57. package/dist/sites/salesforce-developer/index.js +1 -2
  58. package/dist/sites/salesforce-doc-fetch.d.ts +11 -0
  59. package/dist/sites/salesforce-doc-fetch.js +117 -76
  60. package/dist/sites/salesforce-dom-probe.d.ts +16 -0
  61. package/dist/sites/salesforce-dom-probe.js +114 -0
  62. package/dist/sites/types.d.ts +0 -6
  63. package/oclif.manifest.json +31 -106
  64. package/package.json +32 -25
  65. package/dist/commands/index.d.ts +0 -35
  66. package/dist/commands/index.js +0 -306
  67. package/dist/commands/research/config/base.d.ts +0 -23
  68. package/dist/commands/research/config/base.js +0 -46
  69. package/dist/commands/research/config/get.d.ts +0 -20
  70. package/dist/commands/research/config/get.js +0 -45
  71. package/dist/commands/research/config/list.d.ts +0 -17
  72. package/dist/commands/research/config/list.js +0 -42
  73. package/dist/commands/research/config/set.d.ts +0 -31
  74. package/dist/commands/research/config/set.js +0 -94
  75. package/dist/commands/research/config/unset.d.ts +0 -21
  76. package/dist/commands/research/config/unset.js +0 -59
  77. package/dist/commands/research/import.d.ts +0 -38
  78. package/dist/commands/research/import.js +0 -313
  79. package/dist/commands/research/inspect.d.ts +0 -13
  80. package/dist/commands/research/inspect.js +0 -86
  81. package/dist/commands/research/list.d.ts +0 -25
  82. package/dist/commands/research/list.js +0 -143
  83. package/dist/commands/research/prune.d.ts +0 -24
  84. package/dist/commands/research/prune.js +0 -141
  85. package/dist/commands/research/search.d.ts +0 -32
  86. package/dist/commands/research/search.js +0 -334
  87. package/dist/commands/research/status.d.ts +0 -17
  88. package/dist/commands/research/status.js +0 -108
  89. package/dist/commands/research.d.ts +0 -36
  90. package/dist/commands/research.js +0 -304
  91. package/dist/commands/search.d.ts +0 -35
  92. package/dist/commands/search.js +0 -391
  93. package/dist/lib/research/docs/__fixtures__/sphinx-searchindex.d.ts +0 -1
  94. package/dist/lib/research/docs/__fixtures__/sphinx-searchindex.js +0 -2
  95. package/dist/lib/research/docs/discovery-index.d.ts +0 -14
  96. package/dist/lib/research/docs/discovery-index.js +0 -112
  97. package/dist/lib/research/docs/remote-search-runner.d.ts +0 -21
  98. package/dist/lib/research/docs/remote-search-runner.js +0 -114
  99. package/dist/lib/research/docs/remote-search.d.ts +0 -14
  100. package/dist/lib/research/docs/remote-search.js +0 -101
  101. package/dist/lib/research/docs/search-index.d.ts +0 -13
  102. package/dist/lib/research/docs/search-index.js +0 -176
  103. package/dist/sites/algolia.d.ts +0 -9
  104. package/dist/sites/algolia.js +0 -26
  105. package/dist/sites/auto.d.ts +0 -8
  106. package/dist/sites/auto.js +0 -30
  107. package/dist/sites/nextjs/index.d.ts +0 -2
  108. package/dist/sites/nextjs/index.js +0 -52
  109. package/dist/sites/react/index.d.ts +0 -2
  110. package/dist/sites/react/index.js +0 -17
  111. package/dist/sites/salesforce/browser-search.d.ts +0 -7
  112. package/dist/sites/salesforce/browser-search.js +0 -82
  113. package/dist/sites/salesforce/coveo.d.ts +0 -23
  114. package/dist/sites/salesforce/coveo.js +0 -161
  115. package/dist/sites/salesforce/token.d.ts +0 -26
  116. package/dist/sites/salesforce/token.js +0 -154
  117. package/dist/sites/tailwind/index.d.ts +0 -2
  118. package/dist/sites/tailwind/index.js +0 -17
  119. package/dist/sites/vue/index.d.ts +0 -2
  120. package/dist/sites/vue/index.js +0 -17
package/README.md CHANGED
@@ -20,7 +20,7 @@ The package is published as `@taurgis/bonsai` and installs a `bonsai` binary.
20
20
  | **Freshness tiers** | Supports `stable`, `standard`, `volatile`, custom TTLs, and stale revalidation | Handling standards differently from release notes or beta docs |
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
- | **Search** | Ranks local cache entries by topic, tags, snippets, fuzzy terms, and phrases | Finding existing research before fetching again |
23
+ | **List** | Filters cached entries by topic, tags, freshness, and metadata | Seeing what is already cached without reading full content |
24
24
 
25
25
  ---
26
26
 
@@ -82,10 +82,10 @@ echo "# My Custom Node API Notes" | npx @taurgis/bonsai import https://nodejs.or
82
82
  echo "# Synthesized React Cache Guide" | npx @taurgis/bonsai import --stdin --topic "React Suspense" --source-url https://react.dev/a --source-url https://react.dev/b
83
83
  ```
84
84
 
85
- ### 5. Search before fetching
85
+ ### 5. List cached entries
86
86
 
87
87
  ```bash
88
- npx @taurgis/bonsai search "node api url"
88
+ npx @taurgis/bonsai list --tags node
89
89
  ```
90
90
 
91
91
  ---
@@ -138,14 +138,6 @@ Display stored YAML frontmatter metadata for a URL.
138
138
  npx @taurgis/bonsai inspect <url>
139
139
  ```
140
140
 
141
- ### `search <query>`
142
-
143
- Search cached research by metadata and content snippets.
144
-
145
- ```bash
146
- npx @taurgis/bonsai search "<keywords>" [flags]
147
- ```
148
-
149
141
  ### `list`
150
142
 
151
143
  List cached artifacts by metadata filters (`--topic`, `--tags`, `--freshness`, `--artifact-type`, `--capture-method`, `--limit`), newest first, without printing content.
@@ -156,7 +148,7 @@ npx @taurgis/bonsai list [flags]
156
148
 
157
149
  ### `prune`
158
150
 
159
- Delete old or inactive cache entries. Requires a filter (`--older-than`, `--inactive`, or `--artifact-type`) and either `--dry-run` or `--yes`.
151
+ 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).
160
152
 
161
153
  ```bash
162
154
  npx @taurgis/bonsai prune --older-than 90d --dry-run
@@ -281,7 +273,9 @@ When run with `--json`, commands return a stable envelope:
281
273
  | --- | --- |
282
274
  | `BONSAI_STORAGE` | Override the default storage location per-invocation (`global` or `project`). |
283
275
  | `BONSAI_SUMMARY` | Override the summary compression level per-invocation (`conservative`, `balanced`, or `aggressive`). |
284
- | `NO_COLOR` | Disable all ANSI color output (also respected via `TERM=dumb`). |
276
+ | `NO_COLOR` | Set to any non-empty value to disable all ANSI color output. An empty `NO_COLOR` is treated as unset. |
277
+ | `FORCE_COLOR` | Set to any value other than an empty string, `0`, or `false` to force ANSI color on, even in non-TTY environments. |
278
+ | `TERM=dumb` | Disables ANSI color output when the terminal cannot render escape sequences. |
285
279
  | `NO_UPDATE_NOTIFIER` | Suppress the "update available" notification. |
286
280
  | `CI` | Set to `1` or `true` to suppress the update notification in CI environments (detected automatically). |
287
281
  | `DEBUG` | Enable debug output for specific Bonsai namespaces, e.g. `DEBUG=bonsai:*`. |
@@ -5,7 +5,7 @@ model: 'Auto'
5
5
  tools: ['vscode/askQuestions', 'execute', 'read', 'search', 'web', 'vscode/memory']
6
6
  argument-hint: 'What topic should I research in official docs?'
7
7
  metadata:
8
- version: '3.0.1'
8
+ version: '4.0.0'
9
9
  ---
10
10
 
11
11
  # Official Docs Researcher Agent
@@ -18,54 +18,34 @@ Use this agent for technical changes, platform behavior, APIs, SDKs, standards,
18
18
 
19
19
  Do not research from memory alone. Training-data knowledge does not satisfy this workflow.
20
20
 
21
- ## Default Workflow
21
+ ## Invocation
22
22
 
23
- 1. Identify the product, version, edition, and source authority needed for the request.
24
- 2. Search the Bonsai cache first:
23
+ Run Bonsai as `npx @taurgis/bonsai ...`. Add `--json` when you need structured output.
25
24
 
26
- ```bash
27
- # 1. Default search: Checks the local cache across EVERYTHING you've researched,
28
- # including domains that do not support online search APIs.
29
- bonsai search "<topic or keywords>"
30
-
31
- # 2. Remote API search: Use this to quickly find URLs for documentation pages online
32
- # ONLY if you don't find any information in the local cache.
33
- bonsai search "<topic or keywords>" --domain <domain>
34
- # Supported domains: help.salesforce.com, react.dev, vuejs.org, tailwindcss.com, nextjs.org,
35
- # jestjs.io, cypress.io, vitest.dev, vitepress.dev, angular.dev, redux.js.org,
36
- # vitejs.dev, fastify.dev, rollupjs.org, vueuse.org
37
- ```
25
+ ## Default Workflow
38
26
 
39
- 3. If the cache misses or does not cover the question, locate official source URLs. Prefer vendor docs, standards bodies, API references, and official release notes.
40
- 4. Capture each source through Bonsai:
27
+ 1. Identify the product, version, edition, and source authority needed for the request.
28
+ 2. Locate official source URLs. 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.
29
+ 3. Capture each source through Bonsai:
41
30
 
42
31
  ```bash
43
- bonsai <official-url> --format detailed
32
+ npx @taurgis/bonsai <official-url> --format detailed
44
33
  ```
45
34
 
46
- 5. Use `--rendered` for SPAs or pages where static extraction is incomplete:
35
+ 4. Use `--rendered` for SPAs or pages where static extraction is incomplete:
47
36
 
48
37
  ```bash
49
- bonsai <official-url> --rendered --format detailed
38
+ npx @taurgis/bonsai <official-url> --rendered --format detailed
50
39
  ```
51
40
 
52
- 6. Summarize only what the official sources support. Include source URLs, validation time when available, version notes, and any important limitations.
41
+ 5. Summarize only what the official sources support. Include source URLs, validation time when available, version notes, and any important limitations.
53
42
 
54
- Inside the Bonsai repository, use the development binary instead of an installed global command:
43
+ For structured output:
55
44
 
56
45
  ```bash
57
- node bin/cli.mjs search "<topic or keywords>" --json
58
- node bin/cli.mjs <official-url> --format detailed --json
46
+ npx @taurgis/bonsai <official-url> --format detailed --json
59
47
  ```
60
48
 
61
- For one-shot published usage outside this repo, use the scoped package name:
62
-
63
- ```bash
64
- npx @taurgis/bonsai <official-url> --format detailed
65
- ```
66
-
67
- Do not document or run bare `npx bonsai` unless an unscoped npm shim is actually published.
68
-
69
49
  ## Freshness Policy
70
50
 
71
51
  Choose the freshness tier based on the source:
@@ -81,13 +61,13 @@ Stale volatile sources must be revalidated before they are trusted. Never overwr
81
61
  If direct web access was unavoidable because Bonsai could not fetch the content, import the synthesized notes back into Bonsai before returning:
82
62
 
83
63
  ```bash
84
- bonsai import <url> --file <path>
64
+ npx @taurgis/bonsai import <url> --file <path>
85
65
  ```
86
66
 
87
67
  For multi-source synthesis:
88
68
 
89
69
  ```bash
90
- bonsai import \
70
+ npx @taurgis/bonsai import \
91
71
  --topic "<descriptive topic>" \
92
72
  --source-url <url1> \
93
73
  --source-url <url2> \
@@ -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: '1.0.1'
8
+ version: '2.0.0'
9
9
  ---
10
10
 
11
11
  # Salesforce Docs Researcher Agent
@@ -18,70 +18,43 @@ Use this agent for technical changes, platform behavior, APIs, SDKs, standards,
18
18
 
19
19
  Do not research from memory alone. Training-data knowledge does not satisfy this workflow.
20
20
 
21
- ## Default Workflow
21
+ ## Invocation
22
22
 
23
- 1. Identify the product, version, edition, and source authority needed for the request.
24
- 2. Search the Bonsai cache first:
23
+ Run Bonsai as `npx @taurgis/bonsai ...`. Add `--json` when you need structured output.
25
24
 
26
- ```bash
27
- # 1. Default search: Checks the local cache across EVERYTHING you've researched,
28
- # including domains that do not support online search APIs.
29
- bonsai search "<topic or keywords>"
30
-
31
- # 2. Remote API search: Use this to quickly find URLs for documentation pages online
32
- # ONLY if you don't find any information in the local cache.
33
- bonsai search "<topic or keywords>" --domain <domain>
34
- # Supported domains: help.salesforce.com, react.dev, vuejs.org, tailwindcss.com, nextjs.org,
35
- # jestjs.io, cypress.io, vitest.dev, vitepress.dev, angular.dev, redux.js.org,
36
- # vitejs.dev, fastify.dev, rollupjs.org, vueuse.org
37
- ```
25
+ ## Default Workflow
38
26
 
39
- 3. If the cache misses or does not cover the question, locate official source URLs. Prefer vendor docs, standards bodies, API references, and official release notes.
40
- 4. Capture each source through Bonsai:
27
+ 1. Identify the product, version, edition, and source authority needed for the request.
28
+ 2. Locate official Salesforce source URLs. Use your native web/search tools when you do not yet know the URL.
29
+ 3. Capture each source through Bonsai:
41
30
 
42
31
  ```bash
43
- bonsai <official-url> --format detailed
32
+ npx @taurgis/bonsai <official-url> --format detailed
44
33
  ```
45
34
 
46
- 5. Use `--rendered` for SPAs or pages where static extraction is incomplete:
35
+ 4. Use `--rendered` for SPAs or pages where static extraction is incomplete:
47
36
 
48
37
  ```bash
49
- bonsai <official-url> --rendered --format detailed
38
+ npx @taurgis/bonsai <official-url> --rendered --format detailed
50
39
  ```
51
40
 
52
- 6. Summarize only what the official sources support. Include source URLs, validation time when available, version notes, and any important limitations.
41
+ 5. Summarize only what the official sources support. Include source URLs, validation time when available, version notes, and any important limitations.
53
42
 
54
- Inside the Bonsai repository, use the development binary instead of an installed global command:
43
+ For structured output:
55
44
 
56
45
  ```bash
57
- node bin/cli.mjs search "<topic or keywords>" --json
58
- node bin/cli.mjs <official-url> --format detailed --json
46
+ npx @taurgis/bonsai <official-url> --format detailed --json
59
47
  ```
60
48
 
61
- For one-shot published usage outside this repo, use the scoped package name:
62
-
63
- ```bash
64
- npx @taurgis/bonsai <official-url> --format detailed
65
- ```
66
-
67
- Do not document or run bare `npx bonsai` unless an unscoped npm shim is actually published.
68
-
69
49
  ## Working with Salesforce Sites
70
50
 
71
51
  Salesforce Help and Developer docs are Lightning Web Runtime (LWR) pages: the article text is rendered by JavaScript, so a plain fetch returns an almost-empty shell. Bonsai ships a per-host **site module** that forces browser rendering and runs Salesforce-specific extraction, so a normal Bonsai fetch already returns clean Markdown for these hosts — you do not need to add `--rendered` yourself.
72
52
 
73
53
  | Host | Module | Capabilities |
74
54
  | --- | --- | --- |
75
- | `help.salesforce.com` | `salesforce` (Salesforce Help) | Rendered fetch and live `--domain` search (Coveo backend) |
76
- | `developer.salesforce.com` | `salesforce-developer` (Salesforce Developer) | Rendered fetch only — no search |
77
-
78
- - **Search Help live.** For Help topics where you do not yet have a URL, search Salesforce's own backend instead of guessing:
79
-
80
- ```bash
81
- npx @taurgis/bonsai search "single sign-on" --domain help.salesforce.com
82
- ```
55
+ | `help.salesforce.com` | `salesforce` (Salesforce Help) | Rendered fetch |
56
+ | `developer.salesforce.com` | `salesforce-developer` (Salesforce Developer) | Rendered fetch |
83
57
 
84
- Results come straight from Coveo and are validated against an allow-list of Salesforce documentation hosts. There is no `--domain` search for `developer.salesforce.com`; passing it exits with an error, so find Developer URLs another way, then fetch them through Bonsai.
85
58
  - **Matching is by exact hostname.** `help.salesforce.com` matches; subdomains do not. Prefer canonical `/s/articleView?id=…` Help URLs; Bonsai normalizes legacy `/help_doccontent?id=…` links to them automatically.
86
59
  - **Revalidation re-fetches in full.** Module-fetched pages have no cheap `ETag`/`If-Modified-Since` shortcut, so refreshing a stale Salesforce page does a full re-render. `siteModuleId` in the JSON output confirms which module captured a page.
87
60
 
@@ -100,13 +73,13 @@ Stale volatile sources must be revalidated before they are trusted. Never overwr
100
73
  If direct web access was unavoidable because Bonsai could not fetch the content, import the synthesized notes back into Bonsai before returning:
101
74
 
102
75
  ```bash
103
- bonsai import <url> --file <path>
76
+ npx @taurgis/bonsai import <url> --file <path>
104
77
  ```
105
78
 
106
79
  For multi-source synthesis:
107
80
 
108
81
  ```bash
109
- bonsai import \
82
+ npx @taurgis/bonsai import \
110
83
  --topic "<descriptive topic>" \
111
84
  --source-url <url1> \
112
85
  --source-url <url2> \
@@ -12,7 +12,7 @@ differs.
12
12
  The hooks deny native URL-fetch tools and return model-visible guidance like:
13
13
 
14
14
  ```bash
15
- bonsai https://example.com/docs --format detailed
15
+ npx @taurgis/bonsai https://example.com/docs --format detailed
16
16
  ```
17
17
 
18
18
  Most hook systems cannot transparently replace a web-fetch tool call with a shell
@@ -48,15 +48,8 @@ that tells the agent to prefer Bonsai for URLs.
48
48
 
49
49
  ## Published Command
50
50
 
51
- The examples use `bonsai` on the assumption that the CLI is installed. For
52
- one-shot usage, tell agents to run:
51
+ Run Bonsai through the published npm package:
53
52
 
54
53
  ```bash
55
54
  npx @taurgis/bonsai <url> --format detailed
56
55
  ```
57
-
58
- Inside the Bonsai repository, use the development binary:
59
-
60
- ```bash
61
- node bin/cli.mjs <url> --format detailed
62
- ```
@@ -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 = `bonsai ${url} --format detailed`;
12
+ const command = `npx @taurgis/bonsai ${url} --format detailed`;
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: 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. 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 = `bonsai ${url} --format detailed`;
12
+ const command = `npx @taurgis/bonsai ${url} --format detailed`;
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 = `bonsai ${url} --format detailed`;
12
+ const command = `npx @taurgis/bonsai ${url} --format detailed`;
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 = `bonsai ${url} --format detailed`;
12
+ const command = `npx @taurgis/bonsai ${url} --format detailed`;
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: '1.0.2'
7
+ version: '2.0.0'
8
8
  ---
9
9
 
10
10
  # Web Research Requirement (Salesforce)
@@ -24,23 +24,22 @@ metadata:
24
24
 
25
25
  ## Shared Cache
26
26
 
27
- - **Local Cache Search (Default)**: Always search the local cache first using `bonsai search "<query>"`. This checks everything you've researched across all domains, even ones that don't support online search APIs.
28
- - **Online URL Discovery (Fallback)**: If the local cache comes up empty, use `--domain <domain>` or `--remote <docs-url>` to quickly hit a site's search API and find the official URLs you need to fetch. This is specifically for online URL discovery when local cache fails.
27
+ - **Invocation**: Run Bonsai as `npx @taurgis/bonsai ...`.
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
30
  - 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
31
  - Re-running on a recent topic is cheap — research the topic rather than skipping it to "save" a fetch.
31
- - Supported remote API domains: `help.salesforce.com`, `react.dev`, `vuejs.org`, `tailwindcss.com`, `nextjs.org`, `jestjs.io`, `cypress.io`, `vitest.dev`, `vitepress.dev`, `angular.dev`, `redux.js.org`, `vitejs.dev`, `fastify.dev`, `rollupjs.org`, `vueuse.org`.
32
32
 
33
33
  ## Working with Salesforce Sites
34
34
 
35
35
  Salesforce Help and Developer docs are JavaScript-rendered (LWR), so Bonsai uses per-host **site modules** that render and extract them for you — a normal Bonsai fetch returns clean Markdown for these hosts without `--rendered`.
36
36
 
37
- - **Search Help live** when you do not have a URL yet — this hits Salesforce's own backend, not the local cache:
37
+ - **Help and Developer fetch.** Once you have a URL, capture it through Bonsai:
38
38
 
39
39
  ```bash
40
- npx @taurgis/bonsai search "single sign-on" --domain help.salesforce.com
40
+ npx @taurgis/bonsai <official-url> --format detailed
41
41
  ```
42
42
 
43
- - `developer.salesforce.com` has a rendered fetch but **no** `--domain` search (passing it errors); find Developer URLs another way, then fetch them through Bonsai.
44
43
  - Matching is by exact hostname; prefer canonical `/s/articleView?id=…` Help URLs (Bonsai normalizes legacy `/help_doccontent?id=…` links automatically).
45
44
 
46
45
  ## When Not to Use
@@ -52,7 +51,7 @@ Salesforce Help and Developer docs are JavaScript-rendered (LWR), so Bonsai uses
52
51
  ## Examples
53
52
 
54
53
  - ✅ Confirming one platform's current flag or frontmatter field before a small edit → run the web-research skill inline.
55
- - ✅ Finding a Salesforce Help article by topic → `npx @taurgis/bonsai search "<topic>" --domain help.salesforce.com`, then fetch the chosen URL through Bonsai.
54
+ - ✅ Finding a Salesforce Help article by topic → discover the official URL with native web/search tools, then fetch it through Bonsai.
56
55
  - ✅ Comparing conventions across several platforms, or auditing/refactoring source broadly → delegate to the Salesforce Docs Researcher subagent.
57
56
  - ✅ Before editing instructions, prompts, agents, skills, workflows, or docs — reading source code does not replace checking current platform guidance.
58
57
  - ✅ Include official source URLs when the change references platform behavior or standards.
@@ -4,7 +4,7 @@ applyTo: '**'
4
4
  skills:
5
5
  - web-research
6
6
  metadata:
7
- version: '3.1.2'
7
+ version: '4.0.0'
8
8
  ---
9
9
 
10
10
  # Web Research Requirement
@@ -24,11 +24,10 @@ metadata:
24
24
 
25
25
  ## Shared Cache
26
26
 
27
- - **Local Cache Search (Default)**: Always search the local cache first using `bonsai search "<query>"`. This checks everything you've researched across all domains, even ones that don't support online search APIs.
28
- - **Online URL Discovery (Fallback)**: If the local cache comes up empty, use `--domain <domain>` or `--remote <docs-url>` to quickly hit a site's search API and find the official URLs you need to fetch. This is specifically for online URL discovery when local cache fails.
27
+ - **Invocation**: Run Bonsai as `npx @taurgis/bonsai ...`.
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
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
30
  - Re-running on a recent topic is cheap — research the topic rather than skipping it to "save" a fetch.
31
- - Supported remote API domains: `help.salesforce.com`, `react.dev`, `vuejs.org`, `tailwindcss.com`, `nextjs.org`, `jestjs.io`, `cypress.io`, `vitest.dev`, `vitepress.dev`, `angular.dev`, `redux.js.org`, `vitejs.dev`, `fastify.dev`, `rollupjs.org`, `vueuse.org`.
32
31
 
33
32
  ## When Not to Use
34
33
 
@@ -1,52 +1,42 @@
1
1
  ---
2
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 searching/listing/pruning the local research cache, or when importing manually gathered notes.'
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/pruning the local research cache, or when importing manually gathered notes.'
4
4
  license: Forward Proprietary
5
5
  compatibility: VS Code 1.x+, GitHub Copilot
6
6
  metadata:
7
- version: '2.1.1'
7
+ version: '3.0.0'
8
8
  ---
9
9
 
10
10
  # Web Research Skill
11
11
 
12
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
13
 
14
- ## Required Pre-Step
14
+ ## Invocation
15
15
 
16
- Before creating, updating, refactoring, scaffolding, or deleting technical content, verify relevant current official documentation in the same task.
16
+ Always run Bonsai through the published npm package:
17
17
 
18
18
  ```bash
19
- # 1. Default search: Checks the local cache across EVERYTHING you've researched,
20
- # including domains that do not support online search APIs.
21
- bonsai search "<topic or keywords>"
22
-
23
- # 2. Remote API search: Use this to quickly find URLs for documentation pages online
24
- # ONLY if you don't find any information in the local cache.
25
- bonsai search "<topic or keywords>" --domain <domain>
26
- # Supported domains: help.salesforce.com, react.dev, vuejs.org, tailwindcss.com, nextjs.org, jestjs.io, cypress.io, vitest.dev, vitepress.dev, angular.dev, redux.js.org, vitejs.dev, fastify.dev, rollupjs.org, vueuse.org
19
+ npx @taurgis/bonsai <command> [flags]
27
20
  ```
28
21
 
29
- If the cache misses or does not cover the question, fetch the source through Bonsai:
22
+ Add `--json` when you need machine-readable output for agent callers.
30
23
 
31
- ```bash
32
- bonsai <official-url> --format detailed
33
- ```
24
+ ## Required Pre-Step
34
25
 
35
- Inside the Bonsai repository, use the development binary:
26
+ Before creating, updating, refactoring, scaffolding, or deleting technical content, verify relevant current official documentation in the same task.
27
+
28
+ 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:
36
29
 
37
30
  ```bash
38
- node bin/cli.mjs search "<topic or keywords>" --json
39
- node bin/cli.mjs <official-url> --format detailed --json
31
+ npx @taurgis/bonsai <official-url> --format detailed
40
32
  ```
41
33
 
42
- For one-shot published usage outside this repo, use the scoped package name:
34
+ For agent callers that need structured output:
43
35
 
44
36
  ```bash
45
- npx @taurgis/bonsai <official-url> --format detailed
37
+ npx @taurgis/bonsai <official-url> --format detailed --json
46
38
  ```
47
39
 
48
- Do not document or run bare `npx bonsai` unless an unscoped npm shim is actually published.
49
-
50
40
  ## Source Rules
51
41
 
52
42
  - Prefer official vendor docs, standards, API references, SDK docs, release notes, changelogs, and security advisories.
@@ -62,13 +52,11 @@ Use `--format compressed` for context-budgeted reading and `--format detailed` f
62
52
  Use `--rendered` when static extraction is incomplete or the page is an SPA:
63
53
 
64
54
  ```bash
65
- bonsai <official-url> --rendered --format detailed
55
+ npx @taurgis/bonsai <official-url> --rendered --format detailed
66
56
  ```
67
57
 
68
58
  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.
69
59
 
70
- Pure discovery searches are allowed when you do not yet know which URL to fetch. Once a URL is selected, capture it with Bonsai.
71
-
72
60
  ## Manual Fallbacks
73
61
 
74
62
  If direct web access was unavoidable because of authentication, browser interaction, or a tool constraint, import the result into Bonsai before returning.
@@ -76,19 +64,19 @@ If direct web access was unavoidable because of authentication, browser interact
76
64
  Single-source import:
77
65
 
78
66
  ```bash
79
- bonsai import <url> --file path/to/notes.md
67
+ npx @taurgis/bonsai import <url> --file path/to/notes.md
80
68
  ```
81
69
 
82
70
  Stdin import:
83
71
 
84
72
  ```bash
85
- echo "# My Synthesis Note" | bonsai import <url> --stdin
73
+ echo "# My Synthesis Note" | npx @taurgis/bonsai import <url> --stdin
86
74
  ```
87
75
 
88
76
  Multi-source synthesis:
89
77
 
90
78
  ```bash
91
- bonsai import \
79
+ npx @taurgis/bonsai import \
92
80
  --topic "<descriptive topic>" \
93
81
  --source-url <url1> \
94
82
  --source-url <url2> \
@@ -100,27 +88,26 @@ bonsai import \
100
88
  Check status without fetching:
101
89
 
102
90
  ```bash
103
- bonsai status <url>
91
+ npx @taurgis/bonsai status <url>
104
92
  ```
105
93
 
106
94
  Inspect stored metadata:
107
95
 
108
96
  ```bash
109
- bonsai inspect <url>
97
+ npx @taurgis/bonsai inspect <url>
110
98
  ```
111
99
 
112
- List or search cached entries:
100
+ List cached entries by metadata:
113
101
 
114
102
  ```bash
115
- bonsai list --tags node
116
- bonsai search "react suspense"
103
+ npx @taurgis/bonsai list --tags node
117
104
  ```
118
105
 
119
106
  Preview pruning before deleting:
120
107
 
121
108
  ```bash
122
- bonsai prune --older-than 90d --dry-run
123
- bonsai prune --older-than 90d --yes
109
+ npx @taurgis/bonsai prune --older-than 90d --dry-run
110
+ npx @taurgis/bonsai prune --older-than 90d --yes
124
111
  ```
125
112
 
126
113
  ## When This Does Not Apply
@@ -128,4 +115,4 @@ bonsai prune --older-than 90d --yes
128
115
  - No technical content or web content is involved.
129
116
  - You already fetched and applied current official docs in the current task.
130
117
  - The request is a trivial typo or formatting fix that does not involve platform behavior.
131
- - Bonsai is not installed and `npx @taurgis/bonsai ...` is not available; use the best available official-source workflow and import notes later.
118
+ - `npx @taurgis/bonsai` is unavailable in the environment; use the best available official-source workflow and import notes later.
package/bin/cli.mjs CHANGED
@@ -7,6 +7,7 @@ import updateNotifier from 'update-notifier';
7
7
  import { createRequire } from 'node:module';
8
8
 
9
9
  import { normalizeArgv } from '../dist/lib/argv.js';
10
+ import { tryUnknownHelpOutput } from '../dist/lib/help-preflight.js';
10
11
  import { tryJsonMetaOutput } from '../dist/lib/json-meta.js';
11
12
 
12
13
  const req = createRequire(import.meta.url);
@@ -21,6 +22,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
21
22
  // process.argv itself so both the run path and the help/error path agree.
22
23
  const rawArgv = process.argv.slice(2);
23
24
  const result = normalizeArgv(rawArgv);
25
+ const root = __dirname + '/../';
24
26
 
25
27
  if (result.exitWithJson) {
26
28
  process.exitCode = result.exitWithJson.exitCode;
@@ -28,7 +30,18 @@ if (result.exitWithJson) {
28
30
  process.exit();
29
31
  }
30
32
 
31
- const jsonMeta = await tryJsonMetaOutput(result.argv, __dirname + '/../');
33
+ const unknownHelp = await tryUnknownHelpOutput(result.argv, root);
34
+ if (unknownHelp) {
35
+ process.exitCode = unknownHelp.exitCode;
36
+ if (unknownHelp.kind === 'json') {
37
+ console.log(JSON.stringify(unknownHelp.envelope, null, 2));
38
+ } else {
39
+ console.error(` › Error: ${unknownHelp.message.replaceAll('\n', '\n › ')}`);
40
+ }
41
+ process.exit();
42
+ }
43
+
44
+ const jsonMeta = await tryJsonMetaOutput(result.argv, root);
32
45
  if (jsonMeta) {
33
46
  process.exitCode = jsonMeta.exitCode;
34
47
  console.log(JSON.stringify(jsonMeta.envelope, null, 2));
@@ -45,5 +58,5 @@ process.argv = [process.argv[0], process.argv[1], ...result.argv];
45
58
 
46
59
  await execute({
47
60
  development: false,
48
- dir: __dirname + '/../',
61
+ dir: root,
49
62
  });
@@ -10,10 +10,11 @@ export declare abstract class BaseCommand<T extends typeof Command> extends Comm
10
10
  static enableJsonFlag: boolean;
11
11
  flags: Interfaces.InferredFlags<T['flags']>;
12
12
  args: Interfaces.InferredArgs<T['args']>;
13
+ parsedArgv: string[];
13
14
  init(): Promise<void>;
14
15
  /**
15
16
  * Always surface warnings on stderr, even under `--json`. oclif silences `warn()` in JSON mode,
16
- * but our warnings (secret-redirect, stale-serve, remote-search fallback, prune failures) are
17
+ * but our warnings (secret-redirect, stale-serve, prune failures) are
17
18
  * security- and freshness-relevant side effects users must see. stderr never pollutes the stdout
18
19
  * JSON envelope, so machine output stays clean.
19
20
  */
@@ -37,11 +38,23 @@ export declare abstract class BaseCommand<T extends typeof Command> extends Comm
37
38
  exit?: number;
38
39
  };
39
40
  exitCode?: number;
41
+ code?: string;
40
42
  }): Promise<any>;
41
43
  /** Command id for the JSON envelope; falls back to the binary name when a command has no id. */
42
44
  protected envelopeCommandId(): string;
43
- /** Resolve a URL against the research cache, exiting with INVALID_URL on normalization failure. */
45
+ /**
46
+ * Resolve a URL against the research cache, exiting on a normalization failure. A scheme-less but
47
+ * domain-shaped input reports MISSING_URL_SCHEME — the same code the root `bonsai <url>` shorthand
48
+ * uses — so an agent sees one stable code for "forgot https://" everywhere; truly unparseable input
49
+ * stays INVALID_URL.
50
+ */
44
51
  protected resolveResearchTargetOrFail(url: string, extra?: Pick<ResolveResearchTargetOptions, 'flagOverride' | 'lookup'>): ResolvedResearchTarget;
52
+ /**
53
+ * Single exit point for a URL that failed normalization, shared by every URL-accepting command.
54
+ * The scheme-less message is already self-contained and actionable, so it is surfaced as-is;
55
+ * other parse failures keep the "Invalid URL:" prefix for context.
56
+ */
57
+ protected failInvalidUrl(url: string, message: string): never;
45
58
  /** Single source of truth for the `--json` envelope shape, shared by success and error output. */
46
59
  private envelope;
47
60
  /** Wrap a command's return value in the machine-readable envelope emitted under `--json`. */