typebulb 0.12.0 → 0.13.1

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 (193) hide show
  1. package/README.md +19 -17
  2. package/description.md +1 -1
  3. package/dist/agents/claude/client.js +343 -206
  4. package/dist/agents/claude/styles.css +3 -21
  5. package/dist/ai/aiProvider.d.ts +59 -0
  6. package/dist/ai/aiProvider.d.ts.map +1 -0
  7. package/dist/ai/aiProvider.js +109 -0
  8. package/dist/ai/aiProvider.js.map +1 -0
  9. package/dist/ai/aiProviders.d.ts +28 -0
  10. package/dist/ai/aiProviders.d.ts.map +1 -0
  11. package/dist/ai/aiProviders.js +47 -0
  12. package/dist/ai/aiProviders.js.map +1 -0
  13. package/dist/ai/chat.d.ts +32 -0
  14. package/dist/ai/chat.d.ts.map +1 -0
  15. package/dist/ai/chat.js +5 -0
  16. package/dist/ai/chat.js.map +1 -0
  17. package/dist/ai/index.d.ts +9 -0
  18. package/dist/ai/index.d.ts.map +1 -0
  19. package/dist/ai/index.js +11 -0
  20. package/dist/ai/index.js.map +1 -0
  21. package/dist/ai/protocol.d.ts +18 -0
  22. package/dist/ai/protocol.d.ts.map +1 -0
  23. package/dist/ai/protocol.js +3 -0
  24. package/dist/ai/protocol.js.map +1 -0
  25. package/dist/ai/providers/anthropic.d.ts +123 -0
  26. package/dist/ai/providers/anthropic.d.ts.map +1 -0
  27. package/dist/ai/providers/anthropic.js +130 -0
  28. package/dist/ai/providers/anthropic.js.map +1 -0
  29. package/dist/ai/providers/gemini.d.ts +62 -0
  30. package/dist/ai/providers/gemini.d.ts.map +1 -0
  31. package/dist/ai/providers/gemini.js +136 -0
  32. package/dist/ai/providers/gemini.js.map +1 -0
  33. package/dist/ai/providers/openAI.d.ts +146 -0
  34. package/dist/ai/providers/openAI.d.ts.map +1 -0
  35. package/dist/ai/providers/openAI.js +127 -0
  36. package/dist/ai/providers/openAI.js.map +1 -0
  37. package/dist/ai/providers/openRouter.d.ts +65 -0
  38. package/dist/ai/providers/openRouter.d.ts.map +1 -0
  39. package/dist/ai/providers/openRouter.js +82 -0
  40. package/dist/ai/providers/openRouter.js.map +1 -0
  41. package/dist/ai/sseParser.d.ts +32 -0
  42. package/dist/ai/sseParser.d.ts.map +1 -0
  43. package/dist/ai/sseParser.js +121 -0
  44. package/dist/ai/sseParser.js.map +1 -0
  45. package/dist/ai/stream.d.ts +20 -0
  46. package/dist/ai/stream.d.ts.map +1 -0
  47. package/dist/ai/stream.js +6 -0
  48. package/dist/ai/stream.js.map +1 -0
  49. package/dist/dts/cache.d.ts +30 -0
  50. package/dist/dts/cache.d.ts.map +1 -0
  51. package/dist/dts/cache.js +2 -0
  52. package/dist/dts/cache.js.map +1 -0
  53. package/dist/dts/definitelyTypedProvider.d.ts +20 -0
  54. package/dist/dts/definitelyTypedProvider.d.ts.map +1 -0
  55. package/dist/dts/definitelyTypedProvider.js +93 -0
  56. package/dist/dts/definitelyTypedProvider.js.map +1 -0
  57. package/dist/dts/dtsConfig.d.ts +12 -0
  58. package/dist/dts/dtsConfig.d.ts.map +1 -0
  59. package/dist/dts/dtsConfig.js +24 -0
  60. package/dist/dts/dtsConfig.js.map +1 -0
  61. package/dist/dts/dtsResolver.d.ts +63 -0
  62. package/dist/dts/dtsResolver.d.ts.map +1 -0
  63. package/dist/dts/dtsResolver.js +272 -0
  64. package/dist/dts/dtsResolver.js.map +1 -0
  65. package/dist/dts/fetchDts.d.ts +13 -0
  66. package/dist/dts/fetchDts.d.ts.map +1 -0
  67. package/dist/dts/fetchDts.js +46 -0
  68. package/dist/dts/fetchDts.js.map +1 -0
  69. package/dist/dts/httpFetch.d.ts +17 -0
  70. package/dist/dts/httpFetch.d.ts.map +1 -0
  71. package/dist/dts/httpFetch.js +35 -0
  72. package/dist/dts/httpFetch.js.map +1 -0
  73. package/dist/dts/index.d.ts +14 -0
  74. package/dist/dts/index.d.ts.map +1 -0
  75. package/dist/dts/index.js +14 -0
  76. package/dist/dts/index.js.map +1 -0
  77. package/dist/dts/libManifest.d.ts +41 -0
  78. package/dist/dts/libManifest.d.ts.map +1 -0
  79. package/dist/dts/libManifest.js +109 -0
  80. package/dist/dts/libManifest.js.map +1 -0
  81. package/dist/dts/negativeCacheHelper.d.ts +29 -0
  82. package/dist/dts/negativeCacheHelper.d.ts.map +1 -0
  83. package/dist/dts/negativeCacheHelper.js +44 -0
  84. package/dist/dts/negativeCacheHelper.js.map +1 -0
  85. package/dist/dts/tarballFetcher.d.ts +13 -0
  86. package/dist/dts/tarballFetcher.d.ts.map +1 -0
  87. package/dist/dts/tarballFetcher.js +58 -0
  88. package/dist/dts/tarballFetcher.js.map +1 -0
  89. package/dist/dts/tbTypings.d.ts +15 -0
  90. package/dist/dts/tbTypings.d.ts.map +1 -0
  91. package/dist/dts/tbTypings.js +210 -0
  92. package/dist/dts/tbTypings.js.map +1 -0
  93. package/dist/dts/typeProvider.d.ts +37 -0
  94. package/dist/dts/typeProvider.d.ts.map +1 -0
  95. package/dist/dts/typeProvider.js +30 -0
  96. package/dist/dts/typeProvider.js.map +1 -0
  97. package/dist/dts/typeRefScanner.d.ts +8 -0
  98. package/dist/dts/typeRefScanner.d.ts.map +1 -0
  99. package/dist/dts/typeRefScanner.js +33 -0
  100. package/dist/dts/typeRefScanner.js.map +1 -0
  101. package/dist/dts/typescriptProvider.d.ts +21 -0
  102. package/dist/dts/typescriptProvider.d.ts.map +1 -0
  103. package/dist/dts/typescriptProvider.js +140 -0
  104. package/dist/dts/typescriptProvider.js.map +1 -0
  105. package/dist/dts/virtualFs.d.ts +20 -0
  106. package/dist/dts/virtualFs.d.ts.map +1 -0
  107. package/dist/dts/virtualFs.js +48 -0
  108. package/dist/dts/virtualFs.js.map +1 -0
  109. package/dist/format/chunks.d.ts +20 -0
  110. package/dist/format/chunks.d.ts.map +1 -0
  111. package/dist/format/chunks.js +51 -0
  112. package/dist/format/chunks.js.map +1 -0
  113. package/dist/format/config.d.ts +17 -0
  114. package/dist/format/config.d.ts.map +1 -0
  115. package/dist/format/config.js +13 -0
  116. package/dist/format/config.js.map +1 -0
  117. package/dist/format/detection.d.ts +11 -0
  118. package/dist/format/detection.d.ts.map +1 -0
  119. package/dist/format/detection.js +43 -0
  120. package/dist/format/detection.js.map +1 -0
  121. package/dist/format/index.d.ts +8 -0
  122. package/dist/format/index.d.ts.map +1 -0
  123. package/dist/format/index.js +8 -0
  124. package/dist/format/index.js.map +1 -0
  125. package/dist/format/parse.d.ts +20 -0
  126. package/dist/format/parse.d.ts.map +1 -0
  127. package/dist/format/parse.js +88 -0
  128. package/dist/format/parse.js.map +1 -0
  129. package/dist/format/registry.d.ts +24 -0
  130. package/dist/format/registry.d.ts.map +1 -0
  131. package/dist/format/registry.js +31 -0
  132. package/dist/format/registry.js.map +1 -0
  133. package/dist/format/serialize.d.ts +8 -0
  134. package/dist/format/serialize.d.ts.map +1 -0
  135. package/dist/format/serialize.js +30 -0
  136. package/dist/format/serialize.js.map +1 -0
  137. package/dist/format/yaml.d.ts +4 -0
  138. package/dist/format/yaml.d.ts.map +1 -0
  139. package/dist/format/yaml.js +17 -0
  140. package/dist/format/yaml.js.map +1 -0
  141. package/dist/index.js +401 -89
  142. package/dist/lint/index.d.ts +29 -0
  143. package/dist/lint/index.d.ts.map +1 -0
  144. package/dist/lint/index.js +257 -0
  145. package/dist/lint/index.js.map +1 -0
  146. package/dist/render.js +176 -39
  147. package/dist/resolver/attempt.d.ts +2 -0
  148. package/dist/resolver/attempt.d.ts.map +1 -0
  149. package/dist/resolver/attempt.js +9 -0
  150. package/dist/resolver/attempt.js.map +1 -0
  151. package/dist/resolver/cdnClient.d.ts +46 -0
  152. package/dist/resolver/cdnClient.d.ts.map +1 -0
  153. package/dist/resolver/cdnClient.js +107 -0
  154. package/dist/resolver/cdnClient.js.map +1 -0
  155. package/dist/resolver/cdnConstants.d.ts +10 -0
  156. package/dist/resolver/cdnConstants.d.ts.map +1 -0
  157. package/dist/resolver/cdnConstants.js +10 -0
  158. package/dist/resolver/cdnConstants.js.map +1 -0
  159. package/dist/resolver/index.d.ts +20 -0
  160. package/dist/resolver/index.d.ts.map +1 -0
  161. package/dist/resolver/index.js +20 -0
  162. package/dist/resolver/index.js.map +1 -0
  163. package/dist/resolver/packageRef.d.ts +21 -0
  164. package/dist/resolver/packageRef.d.ts.map +1 -0
  165. package/dist/resolver/packageRef.js +89 -0
  166. package/dist/resolver/packageRef.js.map +1 -0
  167. package/dist/resolver/packageService.d.ts +40 -0
  168. package/dist/resolver/packageService.d.ts.map +1 -0
  169. package/dist/resolver/packageService.js +156 -0
  170. package/dist/resolver/packageService.js.map +1 -0
  171. package/dist/resolver/peerResolver.d.ts +33 -0
  172. package/dist/resolver/peerResolver.d.ts.map +1 -0
  173. package/dist/resolver/peerResolver.js +66 -0
  174. package/dist/resolver/peerResolver.js.map +1 -0
  175. package/dist/resolver/semver.d.ts +17 -0
  176. package/dist/resolver/semver.d.ts.map +1 -0
  177. package/dist/resolver/semver.js +56 -0
  178. package/dist/resolver/semver.js.map +1 -0
  179. package/dist/resolver/types.d.ts +33 -0
  180. package/dist/resolver/types.d.ts.map +1 -0
  181. package/dist/resolver/types.js +2 -0
  182. package/dist/resolver/types.js.map +1 -0
  183. package/dist/resolver/versionResolver.d.ts +29 -0
  184. package/dist/resolver/versionResolver.d.ts.map +1 -0
  185. package/dist/resolver/versionResolver.js +79 -0
  186. package/dist/resolver/versionResolver.js.map +1 -0
  187. package/dist/servers.js +142 -3
  188. package/dist/transpile/index.d.ts +19 -0
  189. package/dist/transpile/index.d.ts.map +1 -0
  190. package/dist/transpile/index.js +23 -0
  191. package/dist/transpile/index.js.map +1 -0
  192. package/dist/tsconfig.tsbuildinfo +1 -0
  193. package/package.json +99 -68
package/README.md CHANGED
@@ -18,7 +18,7 @@ A `.bulb.md` file bundles code, styles, data, and config in one file.
18
18
  - **CLI logging** — `tb.server.log(...)` prints to the CLI's stdout
19
19
  - **Env files** — `.env` / `.env.local` load from cwd, `.env.local` overriding `.env` (an exported shell var wins over both). `--mode <name>` adds `.env.<name>` to switch environments (local/staging/prod); a startup line reports which keys loaded from where.
20
20
  - **Server mode** — `--server` runs only the `**server.ts**` section in Node, skipping the web server. Bulbs with only `**server.ts**` (no `**code.tsx**`) use this mode automatically.
21
- - **Type-check without running** — `typebulb check <file>` runs `tsc --noEmit` against the bulb and exits non-zero on errors. Useful for AI editors / CI.
21
+ - **Type-check without running** — `typebulb check <file>` runs `tsc --noEmit` against the bulb: non-zero exit with diagnostics on errors, a one-line all-clear on stderr on success.
22
22
  - **Filesystem access** — `tb.fs.read()` (UTF-8 text), `tb.fs.readBytes()` (raw `Uint8Array`), and `tb.fs.write()` (text or bytes) for local files. Requires `--trust`.
23
23
  - **Hot reload** — Recompiles on save and refreshes the browser (on by default; disable with `--no-watch`)
24
24
  - **Package resolution** — Client dependencies are automatically resolved by generating import maps (same resolver as typebulb.com). Server dependencies are automatically installed via npm.
@@ -27,7 +27,7 @@ A `.bulb.md` file bundles code, styles, data, and config in one file.
27
27
  - **AI calls** — `tb.ai()` for general-purpose AI (chatbots, agents, experiments). `tb.models()` lists available models. Set API keys in `.env` (see below). Requires `--trust`.
28
28
  - **Sandboxed by default** — A plain `npx typebulb my-app.bulb.md` runs with no filesystem or `server.ts` (like typebulb.com); `--trust` grants those for a run. Trust is **remembered**: `typebulb trust <file>` elevates a bulb once so later plain runs are trusted, `untrust` revokes it, and `--no-trust` forces sandboxed for a single run.
29
29
  - **Predict trust** — `typebulb predict <file>` reports the capability a bulb will likely need (fs / AI / `server.ts`) without running it, so you can decide on `--trust` up front rather than after a mid-run permission failure.
30
- - **Agent viewer** — `typebulb agent:claude` opens the agent viewer, a browser view over a Claude Code session that renders embedded bulbs, KaTeX, and mermaid live inline, plus runs/stops local bulbs (see [Claude](#claude)). `typebulb agent` (no target) is the first command an agent runs: it tells the agent how to show a bulb inline or build one locally. `typebulb skill` prints this whole README as an Agent Skill the agent can read and save.
30
+ - **Agent mirror** — `typebulb agent:claude` opens the agent mirror, a browser view over a Claude Code session that renders embedded bulbs, KaTeX, and mermaid live inline, plus runs/stops local bulbs (see [Claude](#claude)). `typebulb agent` (no target) is the first command an agent runs: it tells the agent how to show a bulb inline or build one locally. `typebulb skill` prints this whole README as an Agent Skill the agent can read and save.
31
31
 
32
32
  ## Quick Start
33
33
 
@@ -117,18 +117,19 @@ npm install -g typebulb
117
117
 
118
118
  ```
119
119
  typebulb [file.bulb.md] Run a bulb (defaults to .bulb.md in cwd)
120
- typebulb agent:claude Open the agent viewer (a Claude Code session)
120
+ typebulb agent:claude Open the agent mirror (a Claude Code session)
121
121
  typebulb agent Start here — how to show a bulb inline or build one locally
122
- (prints the viewer URL when one is up); always exits 0
122
+ (prints the mirror URL when one is up); always exits 0
123
123
  typebulb skill Print this README as an Agent Skill on stdout
124
+ typebulb call <file> <fn> […] Invoke one server.ts export headlessly: prints its return as JSON to stdout, logs/errors to stderr (needs --trust)
124
125
  typebulb check [file.bulb.md] Type-check a bulb without running it
125
126
  typebulb predict [file] Report the capability a bulb probably needs, without running it
126
127
  typebulb models List AI models for tb.ai, filtered by your .env API keys
127
128
  typebulb logs [file|pid] Print a running bulb's captured console (no arg: list running servers; -f follow, -n N tail)
128
129
  typebulb stop [file|pid] Stop a running bulb (no arg: list this project's running servers)
129
- typebulb stop --bulbs Stop this project's bulbs; the agent viewer keeps running
130
- typebulb stop --agent Stop this project's agent viewer; its bulbs keep running
131
- typebulb stop --global Stop every running bulb and viewer, all projects (housekeeping)
130
+ typebulb stop --bulbs Stop this project's bulbs; the agent mirror keeps running
131
+ typebulb stop --agent Stop this project's agent mirror; its bulbs keep running
132
+ typebulb stop --global Stop every running bulb and mirror, all projects (housekeeping)
132
133
  typebulb trust [file] Remember a bulb as trusted (no arg: list trusted bulbs)
133
134
  typebulb untrust <file> Forget a bulb's trust (back to sandboxed)
134
135
  typebulb --no-watch <file> Disable hot reload
@@ -198,7 +199,7 @@ A bulb is a single **markdown** file — the minimum viable structure for a smal
198
199
  | `**data.txt**` | Read-only data your code processes via `tb.data(n)` (raw string) / `tb.json(n)` (parsed) — JSON, CSV, XML, YAML, or plain text. Multiple chunks are separated by **two blank lines**. |
199
200
  | `**infer.md**` / `**insight.json**` | Runtime one-shot LLM call via `tb.infer()` — a typebulb.com feature; not supported locally. |
200
201
  | `**notes.md**` | Persistent context for the AI assistant, carried across conversations and clones. Not run. |
201
- | `**server.ts**` | Node.js code; its exports become `tb.server.<name>()` in the browser. **Local only.** |
202
+ | `**server.ts**` | Node.js code; its exports become `tb.server.<name>()` in the browser. Plain Node — no `tb`; log with `console.log`. **Local only.** |
202
203
 
203
204
  ## The `tb.*` API, by target
204
205
 
@@ -228,7 +229,7 @@ A local `.bulb.md` can be re-imported into typebulb.com. If it has a `**server.t
228
229
 
229
230
  ## Claude
230
231
 
231
- The agent viewer currently supports Claude Code only. `npx typebulb agent:claude` gives the user a great scratchpad experience:
232
+ The agent mirror currently supports Claude Code only. `npx typebulb agent:claude` gives the user a great scratchpad experience:
232
233
 
233
234
  * a view over the Claude Code session, where assistant messages containing bulbs render as sandboxed embedded bulbs inline in the conversation, alongside KaTeX math, mermaid diagrams and svg.
234
235
  * run and stop any bulb in their project.
@@ -241,7 +242,7 @@ To keep this skill on hand across sessions, run `npx typebulb skill` and copy it
241
242
  ### When Claude should output local vs embedded bulbs
242
243
 
243
244
  - **First, can it even embed?** A bulb needing `tb.ai`, `tb.fs`, or `server.ts` must be **local** — embeds are client-only, so those calls fail there. The choice below is only for client-only bulbs.
244
- - **Is anyone watching?** An embed only renders live when the agent viewer is open; with none it shows as raw text. `typebulb agent` tells you which case you're in. If no viewer is up and you want to show something inline, start it yourself — `npx typebulb agent:claude --no-open` — and share the link; don't make the user do it.
245
+ - **Is anyone watching?** An embed only renders live when the agent mirror is open; with none it shows as raw text. `typebulb agent` tells you which case you're in. If no mirror is up and you want to show something inline, start it yourself — `npx typebulb agent:claude --no-open` — and share the link; don't make the user do it.
245
246
  - **Something to see right now, in the flow of the conversation** — a chart of some numbers, a quick simulation, an illustrative widget. → **embedded**: emit it in a `bulb` block so it renders live inline.
246
247
  - **A tool worth keeping** — something to reuse, run on its own, or refine over several turns. → **local**: write a `.bulb.md` file run with `npx typebulb`. An embedded block is throwaway and can't be edited in place, so it's the wrong fit for anything iterative.
247
248
 
@@ -249,21 +250,21 @@ To keep this skill on hand across sessions, run `npx typebulb skill` and copy it
249
250
 
250
251
  To render a bulb live inline, wrap the **entire** bulb — frontmatter and all blocks — in a fenced code block whose opening line is **four backticks immediately followed by `bulb`**, and whose closing line is four backticks. Four, not three, so the bulb's own triple-backtick code fences nest inside without prematurely closing the outer block.
251
252
 
252
- The agent viewer turns that block into a live, sandboxed app, with a *breakout ↗* control that saves it as a `.bulb.md` in the `typebulbs/` folder — editable with hot reload, and sandboxed unless you trust it. Embedded bulbs are client-only — no `server.ts`, no `tb.fs`/`tb.ai`, no storage.
253
+ The agent mirror turns that block into a live, sandboxed app, with a *breakout ↗* control that saves it as a `.bulb.md` in the `typebulbs/` folder — editable with hot reload, and sandboxed unless you trust it. Embedded bulbs are client-only — no `server.ts`, no `tb.fs`/`tb.ai`, no storage.
253
254
 
254
- **Fixing a broken embed?** Re-emit it under the *same* `name:` — the viewer folds the old version into a stub and keeps your fix as the live one. (A rename is treated as a new bulb.)
255
+ **Fixing a broken embed?** Re-emit it under the *same* `name:` — the mirror folds the old version into a stub and keeps your fix as the live one. (A rename is treated as a new bulb.)
255
256
 
256
- **A broken embed reads back.** Emit it and move on; embeds usually just work. If the user says one broke, the viewer has already forwarded its compile/runtime error to `typebulb logs claude`, name-tagged (`[embed <name>]`) — pull it from there and fix, instead of asking the user to copy-paste.
257
+ **A broken embed reads back.** Emit it and move on; embeds usually just work. If the user says one broke, the mirror has already forwarded its compile/runtime error to `typebulb logs claude`, name-tagged (`[embed <name>]`) — pull it from there and fix, instead of asking the user to copy-paste.
257
258
 
258
259
  ## Sizing
259
260
 
260
261
  The host owns a bulb's **width**; you own its **height**.
261
262
 
262
- **Width is the host's.** Standalone, a bulb fills its browser window; in the agent viewer, an embed fits the conversation column by default, with a per-embed *spread* toggle to the full transcript width — and a cap so a tall embed doesn't run away down the transcript. Don't set a width or guess how much room you'll get.
263
+ **Width is the host's.** Standalone, a bulb fills its browser window; in the agent mirror, an embed fits the conversation column by default, with a per-embed *spread* toggle to the full transcript width — and a cap so a tall embed doesn't run away down the transcript. Don't set a width or guess how much room you'll get.
263
264
 
264
- **Height follows your content.** Prose, a form, a chart flow to their natural height — set none. A full-bleed canvas has no natural height: give its root `height: 100dvh` **and** a pixel floor like `min-height: 420px`. Both are needed — `100dvh` fills its own window if the bulb is broken out, and the floor holds a definite band when embedded. Without the floor a bare `100dvh` collapses to zero embedded, because the viewer sizes an embed to its content height and `100dvh` gives it nothing to measure against.
265
+ **Height follows your content.** Prose, a form, a chart flow to their natural height — set none. A full-bleed canvas has no natural height: give its root `height: 100dvh` **and** a pixel floor like `min-height: 420px`. Both are needed — `100dvh` fills its own window if the bulb is broken out, and the floor holds a definite band when embedded. Without the floor a bare `100dvh` collapses to zero embedded, because the mirror sizes an embed to its content height and `100dvh` gives it nothing to measure against.
265
266
 
266
- **When embedded, keep vertical space on the root in `padding`, not `margin`.** The viewer measures an embed by `document.body.scrollHeight`, and the runtime makes `body` a block formatting context so a root child's vertical margin (yours, or a UA default like `<h1>`'s) is contained rather than escaping the measurement — so you no longer have to get this exactly right. It's still cleaner to keep the horizontal `auto` for centering and move the vertical space to padding:
267
+ **When embedded, keep vertical space on the root in `padding`, not `margin`.** The mirror measures an embed by `document.body.scrollHeight`, and the runtime makes `body` a block formatting context so a root child's vertical margin (yours, or a UA default like `<h1>`'s) is contained rather than escaping the measurement — so you no longer have to get this exactly right. It's still cleaner to keep the horizontal `auto` for centering and move the vertical space to padding:
267
268
 
268
269
  ```css
269
270
  .wrap { margin: 0 auto; padding: 24px 16px; } /* not: margin: 24px auto */
@@ -274,13 +275,14 @@ The host owns a bulb's **width**; you own its **height**.
274
275
  - **`config.json` `description`** is the bulb's SEO meta description — keep it to one or two plain sentences (~150–160 chars), or it gets truncated.
275
276
  - **The frontmatter `name:` is the bulb's title** — a few words, not a sentence — and the filename should be its slug (`name: Counter` → `counter.bulb.md`).
276
277
  - **Self-testing a local bulb** — To confirm a bulb works, run it, instrument with `tb.server.log(...)` (prints to the server's stdout, captured in the log — and works **even on a sandboxed bulb**), and read it back with `typebulb logs`. That's the loop to verify behaviour without asking the user to copy-paste console output. `tb.fs.write(...)` is handy for dumping large outputs.
278
+ - **Testing a `server.ts` export directly** — `typebulb call <file> <fn> [arg…]` boots `server.ts`, invokes one export, and prints its return as JSON to stdout (logs/errors to stderr, so `… | jq` works). Args after `<fn>` are JSON-or-string; `--args '<json-array>'` (or `--args -` for stdin) escapes tricky quoting. Needs `--trust`.
277
279
  - **Mount to the container your `index.html` declares.** The corpus convention is `<div id="root"></div>` with `createRoot(document.getElementById("root")!)`.
278
280
  - **All imports at the top of `code.tsx`.** Bare imports (`react`, `d3`, `three`, …) auto-resolve from a CDN — no install step. Declare them in `config.json` `dependencies` anyway: that's what lets `npx typebulb check` fetch type defs (without it you get errors like `TS2875: react/jsx-runtime`) and pins versions.
279
281
  - **Theme-aware styling.** Style off CSS variables / `currentColor` so the bulb reads correctly in both light and dark; the host sets the theme.
280
282
  - **`tb.ai()` takes more than the basics** — the full shape is `tb.ai({ messages, system?, reasoning?, provider?, model?, webSearch? })` → `Promise<{ text }>` (non-streaming). `webSearch` defaults **on** in the CLI (you supply your own key); pass `webSearch: false` to turn it off.
281
283
  - **`tb.theme` drives the `html[data-theme]` attribute** — style off that selector (`html[data-theme="dark"] { … }`); don't read `tb.theme` to branch your rendering.
282
284
  - **`color-scheme` is set for you** — the host always applies `html[data-theme="dark"] { color-scheme: dark }` / `html[data-theme="light"] { color-scheme: light }` on top of your `styles.css`.
283
- - **Math renders live in the viewer** — write inline math as `$…$` and display math as `$$…$$` (the viewer renders KaTeX; a plain terminal chat doesn't, so reach for real math here). Prefer `$y = x^2$` over inline-code or a Unicode superscript (`y = x²`).
285
+ - **Math renders live in the mirror** — write inline math as `$…$` and display math as `$$…$$` (the mirror renders KaTeX; a plain terminal chat doesn't, so reach for real math here). Prefer `$y = x^2$` over inline-code or a Unicode superscript (`y = x²`).
284
286
  - **`tb.json<T>(n)` is generic** — `tb.json<Album[]>(0)` returns typed parsed JSON; `tb.data(n)` returns the raw string.
285
287
  - **`tb.proxy()` is for same-origin Web Worker / WASM loads** — e.g. ffmpeg or tesseract: `tb.proxy("https://unpkg.com/...")` routes the CDN URL through the local server's origin.
286
288
  - **Prefer an `index.html` fragment** over a full HTML document — usually just the mount stub (`<div id="root"></div>`).
package/description.md CHANGED
@@ -1,6 +1,6 @@
1
1
  Author and run Typebulb bulbs — single-file markdown apps (TypeScript/TSX) that run
2
2
  locally via `npx typebulb` (full power: filesystem, database, `server.ts`, `tb.ai`) or
3
- render live inline in a Claude Code session through Typebulb's agent viewer (sandboxed,
3
+ render live inline in a Claude Code session through Typebulb's agent mirror (sandboxed,
4
4
  client-only). A bulb can be a visual widget (chart, simulation, diagram, calculator, UI),
5
5
  a full-stack tool with a Node backend, or an AI app that calls models at runtime. Covers
6
6
  the bulb format, the `tb.*` API, trust, and the local run/embed workflow. Use when the