Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 109 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,72 +1,113 @@
<a id="readme-top"></a>
<div align="center">

<img src="./static/readme/browsercode.webp" alt="BrowserCode — run AI coding CLIs in the browser" width="300" />

<br />

# Build web apps that embed AI coding CLIs
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not correct and confusing


BrowserCode is an open source project built on [BrowserPod](https://browserpod.io/), a serverless runtime with a POSIX filesystem, `bash`, `git`, `npm`, and live previews, all running client-side via WebAssembly.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'Serverless' means "run on edge server". Does not mean run in a browser.


[![Discord server](https://img.shields.io/discord/988743885121548329?style=flat-square&color=%235865F2&logo=discord&logoColor=%23fff&label=discord)](https://discord.gg/8ySMrQv6X)
[![Issues](https://img.shields.io/github/issues/leaningtech/browsercode?style=flat-square&logo=github)](https://github.com/leaningtech/browsercode/issues)
[![Version](https://img.shields.io/badge/version-0.5.0-blue?style=flat-square)](package.json)
[![License](https://img.shields.io/badge/license-Apache--2.0-green?style=flat-square)](LICENSE.txt)
[![npm](https://img.shields.io/npm/v/browserpod)](https://npm.im/browserpod)

[Try it live](https://browsercode.io) · [Quickstart](#quickstart) · [How it works](#how-it-works) · [Roadmap](#roadmap) · [BrowserPod docs](https://browserpod.io/docs)

</div>

---

<div align="center">
<img
src="./static/readme/browsercode-lockup-trans-black-text.webp"
alt="BrowserCode logo"
width="400"
/>

<br>

[![Discord server](https://img.shields.io/discord/988743885121548329?color=%235865F2&logo=discord&logoColor=%23fff)](https://discord.gg/8ySMrQv6X)
[![Issues](https://img.shields.io/github/issues/leaningtech/browsercode)](https://github.com/leaningtech/browsercode/issues)
![Version](https://img.shields.io/badge/version-0.5.0-blue)

<h1>Run AI coding CLIs in the browser</h1>

<p>
The BrowserPod runtime to build projects that embed AI coding CLIs.
</p>

<img src="./static/readme/screenshot-hero.webp" alt="Claude Code running in BrowserCode, scaffolding an Express.js app with a live preview" width="100%" />

</div>

<h2 id="table-of-contents">Table of contents</h2>
## What is BrowserCode?

BrowserCode is a runtime for AI coding CLIs. Using [BrowserPod](https://browserpod.io/), the POSIX filesystem, the dev server, and the network proxy all run **inside the user's browser tab** via WebAssembly. It boots instantly.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not agree with this. It's an demo or integration of BrowserPod to run coding CLIs maybe?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The network proxy also by definition does not run in the browser


This repo is the demo: a shell that boots [Claude Code](https://www.anthropic.com/claude-code) and [Gemini CLI](https://github.com/google-gemini/gemini-cli) (with [Codex](https://openai.com/codex) and [OpenCode](https://opencode.ai) on the way), each in its own route, each with a live preview pane fed by BrowserPod's portal function.

## Quickstart

### Use it

- [What is BrowserCode?](#about)
- [Quickstart](#quickstart)
- [Breaking BrowserCode](#breaking-browsercode)
- [Roadmap](#roadmap)
Just open **[browsercode.io](https://browsercode.io)**. The default route boots Claude Code in your browser; switch CLIs from the sidebar or by visiting:

<h2 id="about">What is BrowserCode?</h2>
| Route | CLI |
| --- | --- |
| [`/claude`](https://browsercode.io/claude) | Claude Code |
| [`/gemini`](https://browsercode.io/gemini) | Gemini CLI |
| [`/codex`](https://browsercode.io/codex) | Codex *(coming soon)* |
| [`/opencode`](https://browsercode.io/opencode) | OpenCode *(coming soon)* |

BrowserCode is a browser runtime for AI coding CLIs. BrowserCode is a working example of [BrowserPod](https://browserpod.io/), it includes:
Depending on your auth method, you may be asked to copy a code from a separate tab. After that, prompt the agent like you would on your laptop — except the filesystem it edits, the `npm install` it runs, and the dev server it spins up are all living in the same tab.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Difficult to parse sentence


- Node.js v22 running in the browser via WebAssembly
- A browser-contained, POSIX-like filesystem
- Command line tools: bash, git, npm
- Browser sandbox isolation from the user's operating system
- Restricted outbound networking
- Instant previews over URL via BrowserPod's portal function
- Support for Express.js, Svelte, Next, Nuxt and React (with Wasm overrides)
### Run it locally

BrowserCode 0.5.0 is our second beta release. This preview launches with an unmodified version of Claude Code (with Gemini available too) running completely client-side.
```bash
git clone https://github.com/leaningtech/browsercode.git
cd browsercode
npm install
```

<h2 id="quickstart">Quickstart</h2>
You'll need a BrowserPod API key (`VITE_API_KEY`) from [browserpod.io](https://browserpod.io/) before `npm run dev` will boot a Pod.

<img
align="right"
src="./static/readme/screenshot_mockup.webp"
alt="Gemini CLI running in BrowserCode on BrowserPod"
width="300"
/>
## How it works

1. Go to [browsercode.io](https://browsercode.io)
2. BrowserCode will boot instantly, opening with a quick modal tutorial to guide you
3. Claude Code will launch instantly
4. Depending on your log-in option, you may be asked to authenticate your account by copying a code from a separate tab

<br clear="right" />
The shell does three things:

<h2 id="breaking-browsercode">Breaking BrowserCode</h2>
This is BrowserCode beta. Don't be kind to it. Stretch it, bend it, find out what breaks. Here are a few walls you might hit:
1. **Boots a Pod per route.** `/[tool]/+page.svelte` calls `bootCLI(tool)` from [src/lib/utils/main.ts](src/lib/utils/main.ts), which loads `@leaningtech/browserpod`, mounts the right disk image (e.g. `claude_20260506.ext2`), and runs the CLI's entrypoint inside the sandbox.
2. **Wires a terminal.** `pod.createDefaultTerminal()` is bound to the `#console` element so the CLI's stdio renders in the page.
3. **Surfaces previews via the portal.** When something inside the Pod starts a server, BrowserPod's `onPortal` callback fires with a public URL. The Portal pane embeds that URL, with copy-link and QR-code affordances.

- At launch, Claude is prompted using a custom skill to help it understand that it is running in a custom environment. However, it may first attempt its default behaviour before referencing the file
- BrowserCode doesn't yet support native binaries, for more information, see the [BrowserPod documentation](https://browserpod.io/docs/guides/native-binaries)
- Networking over TCP isn't available
- For maximum compatbility, please use a Chromium browser. Safari currently isn't supported
Per-tool config — disk image, command, args, optional auth-redirect rewrite — lives in [src/lib/config/tools.ts](src/lib/config/tools.ts).

## What's included

<h2 id="roadmap">Roadmap</h2>
| | |
|---|---|
| **Node.js, in the browser** | A Node runtime compiled to Wasm with `bash`, `git`, `npm`, and standard coreutils. Files can persist via OPFS / IndexedDB. |
| **Instant previews via portal URLs** | Any port a process opens inside the Pod gets a public preview URL through BrowserPod's portal. |
| **Cross-origin isolated** | `COOP`/`COEP`/`CORP` headers required by BrowserPod, configured in [_headers](_headers) and [vite.config.ts](vite.config.ts). |
| **Frameworks supported** | Express, Next, Nuxt, and React work out of the box (with Wasm overrides — see below). |

## Project layout

```text
browsercode/
├── src/
│ ├── routes/ # one route per CLI: /claude, /gemini, ...
│ └── lib/
│ ├── components/ # Terminal, Portal, Sidebar, Stepper, UtilityBar
│ ├── config/tools.ts # CLI registry + per-tool BrowserPod config
│ └── utils/main.ts # bootCLI() — mounts the Pod and runs the CLI
├── static/
│ ├── project/
│ │ ├── claude/CLAUDE.md # shipped into the Pod for Claude Code
│ │ └── gemini/GEMINI.md # shipped into the Pod for Gemini CLI
│ └── readme/ # README assets
├── _headers # COOP/COEP/CORP for cross-origin isolation
└── vite.config.ts # same headers, mirrored for dev
```

## Breaking BrowserCode

This is BrowserCode's second beta. Don't be kind to it. Stretch it, bend it, find out what breaks. A few walls you might hit:

- **The agent may ignore its primer on the first turn.** The `CLAUDE.md` / `GEMINI.md` shipped into the Pod tells the model it's running on Wasm, but it can default to its usual behavior before consulting the file. Re-prompt or remind it.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is true at all

- **No native binaries.** See [Wasm overrides](#the-single-most-important-constraint-wasm-overrides) above. If `npm install` blows up, this is almost always why.
- **Networking over TCP isn't available.**
- **Use a Chromium browser for maximum compatibility.** Safari isn't supported.

More edge cases live in the [BrowserPod docs](https://browserpod.io/docs/guides/native-binaries).

## Roadmap

| | CLI | Status |
| :---: | --- | --- |
Expand All @@ -75,5 +116,20 @@ This is BrowserCode beta. Don't be kind to it. Stretch it, bend it, find out wha
| <img src="./static/readme/codex.webp" alt="Codex" width="32" height="32" /> | **Codex** | 🚧 Coming soon |
| <img src="./static/readme/opencode.webp" alt="OpenCode" width="32" height="32" /> | **OpenCode** | 🚧 Coming soon |

## Contributing

Issues and PRs are welcome — especially: more CLI integrations, Wasm overrides we've missed, and reproductions for crashes/hangs you find while breaking it.

<p align="right">(<a href="#readme-top">back to top</a>)</p>
For platform-level questions (BrowserPod itself, disk images, native-binary support), the right venue is the [BrowserPod issue tracker](https://github.com/leaningtech/browserpod) and the [Discord](https://discord.gg/8ySMrQv6X).

## License

Apache-2.0 — see [LICENSE.txt](LICENSE.txt).

---

<div align="center">

Built by [Leaning Technologies](https://leaningtech.com) on top of [BrowserPod](https://browserpod.io/).

</div>
30 changes: 23 additions & 7 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,21 @@
validToolIds.has($page.params.tool as string) ? $page.params.tool : defaultTool
);

let pageTitle = $derived.by(() => {
const tool = toolItems.find((t) => t.id === activePanel);
return tool ? `${tool.label} — BrowserCode` : 'BrowserCode';
});
let activeTool = $derived(toolItems.find((t) => t.id === activePanel));

let pageTitle = $derived(
activeTool ? `${activeTool.label} — BrowserCode` : 'BrowserCode'
);

let pageDescription = $derived(
activeTool
? `Run ${activeTool.label} in your browser, on BrowserCode.`
: 'Run AI coding CLIs in your browser.'
);

let pageUrl = $derived(
activeTool ? `https://browsercode.io/${activeTool.id}` : 'https://browsercode.io'
);

function handlePanelToggle(panel: string) {
if (validToolIds.has(panel)) {
Expand All @@ -31,13 +42,18 @@
<svelte:head>
<title>{pageTitle}</title>
<link rel="icon" href={favicon} />
<meta property="og:title" content="BrowserCode" />
<meta property="og:description" content="Run AI coding CLIs in-browser." />
<meta name="description" content={pageDescription} />
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is redundant. There is already a description tag coming from elsewhere. In the page there will be two tags which might confuse crawlers

<meta property="og:title" content={pageTitle} />
<meta property="og:description" content={pageDescription} />
<meta property="og:image" content="https://browsercode.io/og.png" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://browsercode.io" />
<meta property="og:url" content={pageUrl} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={pageTitle} />
<meta name="twitter:description" content={pageDescription} />
<meta name="twitter:image" content="https://browsercode.io/og.png" />
<meta property="twitter:domain" content="browsercode.io" />
<meta property="twitter:url" content={pageUrl} />
<script
defer
data-domain="browsercode.io"
Expand Down
Binary file added static/readme/browsercode.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/readme/screenshot-hero.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.