Opening the settings pane on mobile set activePaneIdx, but the ?pane= URL-sync effect snapped it back to the chat pane on the panes change, so the pane never showed. toggleSettingsPane now returns the new pane id (id generated outside the updater, strict-mode safe); Session's toggleSettingsAndSync pushes ?pane=<id> on mobile when opening (and drops it on close) so the sync effect keeps it active — mirrors the existing addPaneAndSwitch pattern. Desktop unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
boocode
Self-hosted single-user developer chat app. 3-app monorepo: BooChat (read-only chat), BooCoder (write tools + agent dispatch), BooTerm (PTY terminals).
Latest release: v2.2.1-pane-scoped-chats (2026-05-26) · CHANGELOG.md · Current focus: CURRENT.md
Agent navigation: AGENTS.md · Architecture: docs/ARCHITECTURE.md · Engineering reference: CLAUDE.md
Stack
- Node 20, Fastify, postgres (porsager/postgres), ws, zod
- React 18, Vite, TypeScript, Tailwind v4, shadcn/ui
- Postgres 16
- pnpm workspaces
Layout
apps/server— Fastify API + WebSocket + inference loop + file-read toolsapps/web— React frontend; served by Fastify in production, Vite in devapps/booterm— Fastify + node-pty + tmux for in-browser terminal panesapps/coder— Fastify write tools + ACP/PTY dispatcher + MCP server (BooCoder)
Local dev
Requires Node 20, pnpm, Docker (for Postgres), and ripgrep.
# install
pnpm install
# bring up postgres only
cp .env.example .env
# edit POSTGRES_PASSWORD if you like; default DATABASE_URL points at the container
docker compose up -d boocode_db
# run server (port 3000) and web (port 5173) in two shells
DATABASE_URL=postgres://boocode:devpass@127.0.0.1:5500/boochat \
LLAMA_SWAP_URL=http://100.101.41.16:8401 \
pnpm dev:server
pnpm dev:web
The Vite dev server proxies /api and /api/ws/* to the Fastify backend with a
synthetic Remote-User: sam header so the Authelia auth layer can be skipped
during development.
Production
cd /opt/boocode
docker compose up --build -d
Binds to 100.114.205.53:9500 (Tailscale). Authelia is expected to gate the
upstream and inject Remote-User. Postgres binds loopback only.
BooCoder runs as a host systemd service (boocoder.service, port :9502), not in Docker:
pnpm -C apps/server build && pnpm -C apps/coder build
sudo systemctl restart boocoder
curl http://100.114.205.53:9502/api/health
Services
| Service | Port | Description |
|---|---|---|
| BooChat | 100.114.205.53:9500 |
Read-only chat + SPA |
| BooTerm | 100.114.205.53:9501 |
PTY/tmux terminal panes |
| BooCoder | host:9502 | Write tools + agent dispatch + MCP server (systemd service, not Docker) |
| Postgres | 127.0.0.1:5500 |
Shared database (boochat; Docker service boocode_db) |
| codecontext | internal :8080 |
Code graph sidecar (Docker network only) |
What's shipped
See boocode_roadmap.md for full version history. Highlights as of v2.2.1:
- BooChat: streaming chat, file-read tools, compaction, reasoning support, HTML/Markdown artifact panes, cross-repo read grants, MCP client (multi-server + stdio), tool-cost tracking, skills system, builtin agent registry, multi-pane workspace (chat / terminal / coder)
- BooTerm: in-browser terminal panes via tmux + xterm.js, per-session tmux sessions, SSH-out support
- BooCoder (v2.2): write tools (
edit_file,create_file,delete_file,apply_pending,rewind), pending-changes queue with diff UI, Paseo-style provider snapshot (7 providers: boocode, cursor, claude, opencode, goose, qwen, copilot),AgentComposerBar(provider / mode / model / thinking), ACP dispatch with inline permission prompts + tool/reasoning streaming, PTY fallback, Arena, MCP server (6 tools, stdio), CLI client, human inbox, Boomerang orchestration, path-guard fuzz suite, pane-scoped chats (v2.2.1 — each coder/terminal pane owns its chat)
Planned
- v2.3 provider lifecycle — config-backed provider registry (
/data/coder-providers.json), enable/disable toggles, two-tier probe (openspec drafted). SeeCURRENT.md.