Typebulb runs apps in markdown files called bulbs. Designed for tools, visualizations & experiments. A bulb is a single self-contained file, so an agent can inline an app into its reply, and the same file can be published as a stand-alone web app. The "markdown with code blocks" format is one LLMs find natural to write.
Two ways to create and run bulbs:
One API runs everywhere: the same bulb works in typebulb.com's sandbox and locally, and can call AI models at runtime.
New here? Take the interactive tour.
Run bulbs locally via typebulb's agent mirror, which is included in the open-source Typebulb CLI:
npx typebulb agent then draw fireworks." This will launch Typebulb's agent mirror of your sessions.npx typebulb agent from the command line, and the agent mirror will auto-detect Pi. Then type "draw fireworks".The agent mirror is a GUI that mirrors your agent harness to provide a code scratchpad experience. Features:
Pi lets you both prompt and read responses in the agent mirror, so it has an edge.
With Claude Code and Codex the mirror is strictly a read-only view, so you still prompt from their own CLIs. However, this can have benefits, most notably being able to use your subscription key in the case of Claude Code.
typebulb send <file> tb:snapshot lists the page's controls, their names, and its visible text, tb:click and tb:set press a button or fill a field, tb:png saves the canvas as an image, typebulb send <file> selftest --wait returns a self-test's JSON, and typebulb wait <file> blocks until the bulb logs something.server.ts block; exported functions become callable from the code.tsx block running in the browser via tb.server.<name>() (e.g., export async function query(...) → await tb.server.query(...))tb.fs.read() (UTF-8 text), tb.fs.readBytes() (raw bytes), and tb.fs.write() (text or bytes); relative paths resolve to the bulb's own data folder.env and .env.local auto-loaded from cwd, with .env.local winning. --mode <name> also loads .env.<name>, to switch between local, staging and production.tb.log(...) prints to the CLI's stdout. Particularly useful for your LLM to conduct tests and instrument your code.--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.--no-watch)typebulb check <file> type-checks a bulb without running it (runs tsc --noEmit, exits non-zero on errors).node_modules: the pinned version travels inside the file. Server dependencies are automatically installed via npm.tb.infer() works locally too: same confirmation modal and streaming as typebulb.com, against your own .env keys, plus sharing/saving a good run.typebulb trust <file> elevates a bulb once so later plain runs are trusted, and untrust revokes it. typebulb predict <file> reports what a bulb is likely to need without running it.~/.typebulb/cache/, so repeat runs skip the network and warm runs work offline.A bulb has the following trust levels:
| Capability | Inline | Restricted | Trusted |
|---|---|---|---|
| Run code in the browser, use the network | ✅ | ✅ | ✅ |
| Use storage, cookies, background threads, and the GPU | 🚫 | ✅ | ✅ |
Read local files, run Node code with server.ts, use your AI keys | 🚫 | 🚫 | ✅ |
*.bulb.mdfile..bulb.md has when run. A normal localhost page, so storage, cookies, workers and the GPU all work, but Node-backed calls are refused.Every bulb gets a tb object, without importing anything. It covers what a single sandboxed file can't do for itself: read its own data, call an AI model, copy text to the clipboard, find out which theme it's in, and, once you've trusted it on your machine, reach your filesystem and your server.ts.
You won't write these calls. The AI does. The full list is in the typebulb README.
A bulb is one file made of a few named blocks, and each block is a tab in the editor on typebulb.com. Everything except the code is optional, so the smallest bulb really is just code.
| Block | Purpose |
|---|---|
| code.tsx | The app itself: logic and UI |
| styles.css | Styling |
| index.html | Usually just a stub for the app to mount into |
| data.txt | Data for your code to process (JSON, CSV, XML, YAML, or plain text) |
| infer.md | Instructions for a runtime AI call |
| insight.json | The result of that call |
| config.json | The npm packages the bulb uses, and its description |
| notes.md | Persistent context for the AI |
| server.ts | Node.js code, when running locally |
The Data tab holds the content your code processes, structured (JSON, CSV, XML, YAML) or not (plain text). Multiple chunks are separated by two blank lines.
The Data tab is designed to be handled programmatically, as it's often too long to fit into an agent's context window. In the CLI, an agent can read and set it via the get and put commands.
Note: For general-purpose runtime AI calls, use
tb.ai.
This feature is easiest to understand via an example, such as the bach bulb. The user clicks on "AI Compose" and it launches a dialog, where the user types the genre, e.g. "fugue", and then the AI generates a fugue. The AI assistant will write such a bulb for you, but how does this work?
The Infer tab is a prompt for runtime LLM calls. When your code in code.tsx calls tb.infer(), the LLM receives: your inference instructions, an example output (from insight.json), your code.tsx (so it knows the expected JSON shape), and the data.txt to process. A modal shows the user what will be sent; confirm and the LLM streams its response.
The Insight tab holds JSON that serves as both a working example (showing the LLM what shape you expect) and the current output (updated after tb.infer() completes). Your code reads it via tb.insight(). There's no separate JSON Schema. The code IS the schema.
Free tier users are rate limited. Users with their own API keys have no Typebulb-imposed limits (within reason). Runtime inference always uses the user's API keys, or Typebulb's courtesy models, never your API keys.
Persistent context for the AI, carried across conversations and clones. Useful for API docs, examples, or skills the LLM requires.
Typebulb's AI assistant is great for 1-shot bulbs. If you've got a more complex bulb, develop it locally with Claude Code or Codex, and run with the typebulb CLI. When it's ready you can import to typebulb.com.
OpenAI, Anthropic, Gemini and OpenRouter. Bring your own keys. Your keys are used for the AI assistant and tb.infer() calls that you make, but not anyone else who runs your bulb.
| Mode | AI sees your bulb | AI will edit | Use case |
|---|---|---|---|
| Code | Yes | Yes | Default. Sees code, HTML, CSS, notes, truncated data, errors, and logs. |
| Ask | Yes | No | Same context as Code, but when you just want to discuss, not edit code. |
| Chat | No | No | General conversation, unrelated to your bulb. |
| Raw | No | No | No system prompt. Good for prompt testing. |
In Code mode, Typebulb will automatically reply to the AI if it makes a patch error or generates TypeScript errors, with precise details on how to fix them.
Yes, with caveats. Web search is most reliable with native provider integrations (OpenAI/Anthropic/Gemini); OpenRouter support can be model-dependent and less consistent.
This is web search, not browsing. It works best for well-indexed topics (news, popular libraries, recent releases), and may not retrieve obscure npm or GitHub pages from a URL alone.
If you need the AI to use specific documentation, paste excerpts into the Notes tab; for structured data, use the Data tab.
Add console.logs to your code, and logs are automatically fed back to the AI. You can even debug manually, as we automatically generate TypeScript source maps:
code.tsxLocally, your agent does the debugging. It instruments the bulb, runs it, and reads the console back itself, including for a bulb you started from the explorer and are watching in the browser. See What can my agent do with a running bulb? above for how far that goes.
Typebulb is heavily optimized for building responsive bulbs that work beautifully on both mobile and desktop. "alt-enter" toggles between a mobile-friendly portrait layout and full screen.
For building bulbs, Typebulb works on mobile, but is heavily optimized for desktop usage. The mobile experience has one key feature: you can see the bulb's logs, which is useful for testing.
A bulb has 3 possible visibilities adjustable in the toolbar/menu:
When you share a bulb, the user will see any changes you make if you save the bulb and they refresh their browser. The user has a read-only view of your bulb; if they try to edit it, a clone is made.
Yes. Make sure your local bulbs are in the typebulbs/u/<user-slug>folder, to enable syncing. E.g:
| Local file | On typebulb.com |
|---|---|
typebulbs/u/ben/birds.bulb.md | typebulb.com/u/ben/birds |
Create an access token by clicking on your account name on typebulb.com, then copy & paste the token into your .env in your project, using the nameTYPEBULB_TOKEN.
In the bulb explorer, you can now push and pull the bulb to and from typebulb.com. You can also ask your agent to automate that via typebulb push and typebulb pull calls.
<bulb-slug>/assets/ folder, in the same folder as the bulb.server.ts is stripped if pushed to typebulb.com, since it's only meaningful locally.This is what we store:
We don't use your data for training or sell it to third parties. Your AI providers have their own data policies.
Ben Albahari. I worked as a Program Manager at MSFT, and co-authored the C# in a Nutshell series (with my brother, Joe Albahari, the author of the popular LINQPad tool). It's very cheap to maintain, but if it ever got really popular, I'd seek investment.
This changes all the time. Currently it's a transformer that runs in your browser. Also You're Absolutely Right!, a sycophancy benchmark written as a bulb, that automates hundreds of API calls. The bulb approach makes it easy for anyone to inspect or re-run the results.
← Back to Typebulb