A browser-based ACP client. Open a URL, pick an ACP-driven agent (Claude Agent, Codex, Gemini CLI, Goose, Qwen, Auggie, Mistral Vibe, Cursor, Factory Droid, Pi), and chat with it from any browser tab. The agent runs as a subprocess on your local machine — agent-well is the bridge.
This is roughly agent-shell
for the browser, built on the
Agent Client Protocol.
Browser <— HTTP long-poll —> agent-well <— stdio JSON-RPC —> ACP Agent
(localhost) (subprocess)
- Multi-agent registry (Claude / Codex / Gemini / Goose / Qwen / etc.)
- Streaming chat with collapsible tool calls, agent thoughts, plans
- Expandable edit rows —
Edit/Writetool calls auto-open with a side-by-side diff and a+N −Msummary chip - Rich rendering in agent output (driven by a per-session preamble the
bridge prepends — see
src/bridge.ts:EMBED_PREAMBLE):- Allowlisted media tags inline:
<audio>,<video>,<img> - LaTeX math via KaTeX:
$inline$,$$display$$,\[…\],\(…\) - Standard markdown (headings, lists, code blocks, links)
- Allowlisted media tags inline:
- Permission requests surfaced as modal dialogs
- Filesystem read/write on behalf of the agent (
fs/read_text_file,fs/write_text_file) - Full terminal lifecycle (
terminal/create,output,wait_for_exit,kill,release) - Session resume (for agents that advertise the
loadSessioncapability) - Session persistence under
~/.agent-well/sessions/ - Localhost-only binding (
127.0.0.1) + per-launch token in the URL ETag+Last-Modifiedrevalidation on static assets so a browser refresh always picks up the latestpublic/files
Requires Node ≥ 22.7 (for --env-file-if-exists).
npm install
npm run buildYou'll also need the ACP wrapper for whichever agent(s) you want to use. For Claude:
npm install -g @agentclientprotocol/claude-agent-acpSee src/agents/registry.ts for the install hint for each supported
agent.
Create .env in the project root (gitignored) to set your ngrok
hostname — the source has no default, so without this you get the LAN
URL only:
# .env
AGENT_WELL_NGROK_URL=your-reserved.ngrok.ioThen:
npm startnpm start runs node --env-file-if-exists=.env dist/index.js and, when
AGENT_WELL_NGROK_URL is set, spawns ngrok http --url=$AGENT_WELL_NGROK_URL 7777
so the QR points at a public tunnel — you can scan it from any phone,
anywhere. ngrok must be installed and authenticated locally. Leave the
variable unset (or delete .env) to skip the tunnel and use the LAN URL
only.
The server prints a QR code plus the relevant URLs:
Scan with your phone (or open on this machine):
<QR code rendered in the terminal>
Tunnel: https://your-reserved.ngrok.io/?token=<launch-token>
Local: http://127.0.0.1:7777/?token=<launch-token>
LAN: http://192.168.x.y:7777/?token=<launch-token>
Open one of the URLs (or scan the QR from your phone). Click + New, pick an agent and working directory, and start chatting.
- Cancel (visible only while the agent is busy) sends
session/cancelto the ACP subprocess, stopping the current turn cleanly. Already-run side effects (edits, shell commands) are not undone. - Close terminates the ACP subprocess and clears the session from memory; its transcript stays on disk.
All variables can be set in .env (loaded via --env-file-if-exists=.env)
or via the shell environment.
AGENT_WELL_NGROK_URL— ngrok reserved hostname. Unset or empty disables the tunnel.AGENT_WELL_HOST— bind host (default0.0.0.0so phones on your LAN can reach the server). Set to127.0.0.1to restrict to the local machine.AGENT_WELL_PORT— port to bind (default7777).AGENT_WELL_LOG—debug|info|warn|error(defaultinfo). Known-benign stderr noise (e.g.No onPostToolUseHook found …from claude-agent-acp's TodoWrite path) is downgraded todebug.
- Only Claude Agent and Pi have actually been exercised so far. The other
agents are wired up via
src/agents/registry.tsbut untested — PRs with fixes, install hints, or new agents are very welcome. - The server binds to
0.0.0.0by default so other devices on your LAN (e.g., your phone) can connect. The 192-bit per-launch token in the URL is the security boundary: anyone who has the URL can drive the agent on your machine, so don't share it. SetAGENT_WELL_HOST=127.0.0.1if you only want loopback access. - All file paths in ACP are absolute. The fs handlers refuse relative paths.
- Session transcripts are written to
~/.agent-well/sessions/<id>.json. Delete them to forget a session.