typebulb 0.11.2 → 0.11.3

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.
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # typebulb
2
2
 
3
- Run single-file markdown apps that run in many contexts:
3
+ **Typebulb** runs apps in markdown files called **bulbs**. To run bulbs:
4
4
 
5
- 1. Localhost in your browser and optionally in `nodejs`, which can talk via a secure bridge.
6
- 2. Embedded in agent messages when viewed with `npx typebulb agent:claude`.
7
- 3. Published on [typebulb.com](https://typebulb.com) or edited in its online IDE. See [FAQ](https://typebulb.com/faq).
5
+ * `npx typebulb`. When you want a quick local app or tool where the overhead of an entire npm project is overkill *(trivial for your LLM to convert to when you actually need to)*. Can be entirely client code, or both client and nodejs code that talk via a secure bridge.
6
+ * `npx typebulb agent:claude`. When you want to view Claude Code conversations with embedded bulbs in the agent messages.
7
+ * **[typebulb.com](https://typebulb.com)**. When you want to share tools, visualizations, experiments etc. See [FAQ](https://typebulb.com/faq).
8
8
 
9
- `typebulb` serves the first two cases, by compiling and serving hot-reloadable bulbs locally.
9
+ The `typebulb` CLI enables the first two cases, by compiling and serving hot-reloadable bulbs locally.
10
10
 
11
11
  A `.bulb.md` file bundles code, styles, data, and config in one file.
12
12
 
@@ -94,8 +94,8 @@ button {
94
94
  {
95
95
  "description": "A button that increments a counter.",
96
96
  "dependencies": {
97
- "react": "^19.2.3",
98
- "react-dom": "^19.2.3"
97
+ "react": "^19.2.7",
98
+ "react-dom": "^19.2.7"
99
99
  }
100
100
  }
101
101
  ```
@@ -251,7 +251,7 @@ The agent viewer turns that block into a live, sandboxed app, with a *breakout
251
251
 
252
252
  **Sizing is the viewer's job, not yours.** The agent viewer renders each embed *inline* by default — fit to the conversation column, with height capped so a tall bulb doesn't run away — plus a per-embed toggle to *spread* it to the full transcript width and height. Don't fight the layout from inside the bulb: no need to set a width, reserve height, or guess how much room you'll get.
253
253
 
254
- **One layout rule the bulb must get right: vertical space on the root is `padding`, not `margin`.** The embed auto-sizes by reporting `document.body.scrollHeight`, and a vertical margin on the root element *collapses* (a body's first/last child margin escapes through to the viewport) so it isn't captured in that measurement the host then sizes the frame a margin short and you get a stray scrollbar. The page-style `margin: 32px auto` common on a standalone wrapper is exactly this trap. Keep the horizontal `auto` for centering, but move the vertical part to padding:
254
+ **Prefer `padding` over `margin` for vertical space on the root.** 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:
255
255
 
256
256
  ```css
257
257
  .wrap { margin: 0 auto; padding: 24px 16px; } /* not: margin: 24px auto */
@@ -761,7 +761,7 @@ ${h.map(({variableName:p,uniqueLocalName:b})=>` reactHotLoader.register(${p}, "
761
761
  }
762
762
  })();
763
763
  `;function i9t(o){return o.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}var s9t=` *, *::before, *::after { box-sizing: border-box; }
764
- body { margin: 0; font-family: system-ui, -apple-system, sans-serif; }
764
+ body { margin: 0; display: flow-root; font-family: system-ui, -apple-system, sans-serif; }
765
765
  html[data-theme="dark"] { color-scheme: dark; }
766
766
  html[data-theme="light"] { color-scheme: light; }`;function o9t(o,u){let h=p=>p.replace(/<\/script/gi,"<\\/script");return` <script>
767
767
  (function() {
package/dist/index.js CHANGED
@@ -481,7 +481,7 @@ declare const tb: {${en}${tn}${rn}${on}${wo}${nn}${sn}
481
481
  }
482
482
  })();
483
483
  `;function wt(r){return r.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}var vt=` *, *::before, *::after { box-sizing: border-box; }
484
- body { margin: 0; font-family: system-ui, -apple-system, sans-serif; }
484
+ body { margin: 0; display: flow-root; font-family: system-ui, -apple-system, sans-serif; }
485
485
  html[data-theme="dark"] { color-scheme: dark; }
486
486
  html[data-theme="light"] { color-scheme: light; }`;function xt(r,e){let t=n=>n.replace(/<\/script/gi,"<\\/script");return` <script>
487
487
  (function() {
@@ -731,6 +731,6 @@ ${Ji}
731
731
  `);async function v(){await(await import("esbuild")).build({entryPoints:[I.join(c,"client","index.ts")],bundle:!0,platform:"browser",format:"esm",outfile:I.join(a,"client.js")});for(let T of["styles.css","index.html"])Ba(I.join(c,T),I.join(a,T))}let $;if(r.watch&&n){let E=Ma(c),T=!1;$=Ut({dir:E?c:a,onChange:async()=>{if(!T){T=!0;try{E&&await v(),console.log(`Viewer rebuilt. Browser reloading...
732
732
  `),n.emit("reload")}catch(p){console.error("Viewer rebuild failed:",p instanceof Error?p.message:p)}finally{T=!1}}}})}r.open&&await Pe(g);let O=async()=>{console.log(`
733
733
  Shutting down...`),m.close(),$?.(),t(),await Ze(process.pid),process.exit(0)};process.on("SIGINT",O),process.on("SIGTERM",O)}import*as Vs from"path";import{EventEmitter as Na}from"events";async function zs(r,e,t,n,s){let o=ne(t),i=!1,a=async()=>{let{bulb:c,config:l}=await G(r);i||(_e(o,r,c.server),i=!0),await dr(c.server,s,n,l.dependencies)};if(console.log(`Running ${Vs.basename(r)}...`),await a(),e){console.log(`Watching for changes...
734
- `);let c=new Na;c.on("reload",async()=>{try{console.log("Re-running..."),await a()}catch(l){console.error("Error:",l)}}),Lt({bulbPath:r,emitter:c})}}var qs="0.11.2";async function La(){let r=Vr(process.argv.slice(2));if(r.version&&(console.log(`typebulb ${qs}`),process.exit(0)),r.help&&(zr(),process.exit(0)),r.subcommand==="logs"){await rs(r.file||void 0,{follow:r.follow,lines:r.lines});return}if(r.subcommand==="stop"){r.all?await ss():await ns(r.file||void 0);return}if(r.subcommand==="skill"){await Qn(qs);return}if(r.subcommand==="models"){await Kn(r.mode);return}if(r.subcommand==="agent"){if(!r.agentTarget){await Vn();return}_n(r.agentTarget)||(console.error(`Unknown agent '${r.agentTarget}'. Known: ${hr().join(", ")}.`),process.exit(1));let l=await br(process.cwd(),r.agentTarget);if(l){console.log(`Viewer '${r.agentTarget}' is already running for this project:
734
+ `);let c=new Na;c.on("reload",async()=>{try{console.log("Re-running..."),await a()}catch(l){console.error("Error:",l)}}),Lt({bulbPath:r,emitter:c})}}var qs="0.11.3";async function La(){let r=Vr(process.argv.slice(2));if(r.version&&(console.log(`typebulb ${qs}`),process.exit(0)),r.help&&(zr(),process.exit(0)),r.subcommand==="logs"){await rs(r.file||void 0,{follow:r.follow,lines:r.lines});return}if(r.subcommand==="stop"){r.all?await ss():await ns(r.file||void 0);return}if(r.subcommand==="skill"){await Qn(qs);return}if(r.subcommand==="models"){await Kn(r.mode);return}if(r.subcommand==="agent"){if(!r.agentTarget){await Vn();return}_n(r.agentTarget)||(console.error(`Unknown agent '${r.agentTarget}'. Known: ${hr().join(", ")}.`),process.exit(1));let l=await br(process.cwd(),r.agentTarget);if(l){console.log(`Viewer '${r.agentTarget}' is already running for this project:
735
735
  ${l.url}`),r.open&&await Pe(l.url);return}await Hs(r);return}if(r.subcommand==="trust"||r.subcommand==="untrust"){await Fn(r.file||void 0,r.subcommand==="trust");return}let e;if(!r.file||r.file==="."){let l=await En(process.cwd());l||(console.error("No .bulb.md file found in current directory"),process.exit(1)),e=l}else e=X.resolve(r.file);await Gs.access(e).then(()=>!0,()=>!1)||(hr().includes(r.file)&&(console.error(`To open the ${r.file} agent viewer, run: npx typebulb agent:${r.file}`),process.exit(1)),console.error(`File not found: ${e}`),process.exit(1)),e.endsWith(".bulb.md")||(console.error("File must have .bulb.md extension"),process.exit(1));let n=r.file&&r.file!=="."?r.file:X.relative(process.cwd(),e)||X.basename(e),s=`npx typebulb --trust ${n.includes(" ")?`"${n}"`:n}`;if(r.subcommand==="predict"){await Mn(e,s);return}let o=!r.noTrust&&le(e);o&&!r.trust&&console.log("trust: granted from memory (run `typebulb untrust` to revoke)"),r.trust=r.noTrust?!1:r.trust||o;let i;try{i=await G(e)}catch{}let a;if(r.local){i&&!(r.local.name in(i.config.dependencies??{}))&&(console.error(`--replace: '${r.local.name}' is not a dependency in this bulb's config.json; nothing to replace.`),process.exit(1)),i&&(!i.bulb.code||r.server)&&console.warn("warning: --replace has no effect in server mode (the override is client-only).");try{a=await Jr(r.local)}catch(l){console.error(l instanceof Error?l.message:String(l)),process.exit(1)}console.log(`replace: ${a.name} \u2192 ${X.relative(process.cwd(),a.dir)||"."}`)}if(r.subcommand==="check"){await Bn(e,a);return}let c=X.dirname(e);if(i&&i.bulb.server&&(!i.bulb.code||r.server)){r.trust||(console.error(`This bulb runs server-side Node code (server.ts), which --trust must authorize:
736
736
  ${s}`),process.exit(1)),await zs(e,r.watch,r.mode,a,c);return}await ms(e,r,s,a,c)}La().catch(r=>{console.error("Error:",r.message),process.exit(1)});
package/dist/render.js CHANGED
@@ -345,7 +345,7 @@ ${s.map(({variableName:n,uniqueLocalName:i})=>` reactHotLoader.register(${n}, "
345
345
  }
346
346
  })();
347
347
  `;function ic(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}var ac=` *, *::before, *::after { box-sizing: border-box; }
348
- body { margin: 0; font-family: system-ui, -apple-system, sans-serif; }
348
+ body { margin: 0; display: flow-root; font-family: system-ui, -apple-system, sans-serif; }
349
349
  html[data-theme="dark"] { color-scheme: dark; }
350
350
  html[data-theme="light"] { color-scheme: light; }`;function cc(e,t){let s=n=>n.replace(/<\/script/gi,"<\\/script");return` <script>
351
351
  (function() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typebulb",
3
- "version": "0.11.2",
3
+ "version": "0.11.3",
4
4
  "description": "Local bulb runner CLI for Typebulb",
5
5
  "license": "MIT",
6
6
  "engines": { "node": ">=18" },