Ship Paseo-equivalent provider snapshot, AgentComposerBar, ACP dispatch rewrite with streaming/persist, permission prompts, and agent commands. Follow-up: pane-scoped chat resolution, CoderMessageList tool timeline, WS user-delta replace, and inference orphan tool_call stripping. Archive openspec v2-2; update CHANGELOG and CURRENT. Co-authored-by: Cursor <cursoragent@cursor.com>
4.1 KiB
4.1 KiB
BooCode architecture
Last updated: 2026-05-25. Navigation: AGENTS.md. Deep reference: CLAUDE.md.
System overview
flowchart TB
subgraph client [Browser]
SPA["apps/web React SPA"]
end
subgraph edge [Edge]
Caddy --> Authelia
end
subgraph host ["Host 100.114.205.53"]
subgraph docker [Docker boocode_net]
BooChat["boocode container<br/>apps/server + built web<br/>:9500"]
BooTerm["booterm container<br/>apps/booterm<br/>:9501"]
PG[("boocode_db<br/>Postgres 16<br/>database: boochat<br/>host :5500")]
CC["codecontext sidecar<br/>:8080 internal"]
end
BooCoder["boocoder.service<br/>apps/coder<br/>:9502"]
Agents["Host CLI agents<br/>opencode goose claude qwen"]
LLM["llama-swap<br/>100.101.41.16:8401"]
end
Authelia --> SPA
SPA -->|"HTTP /api WS /api/ws"| BooChat
SPA -->|"WS /ws/term"| BooTerm
SPA -->|"HTTP /api/coder proxy<br/>WS direct"| BooCoder
BooChat --> PG
BooTerm --> PG
BooCoder --> PG
BooChat -->|"HTTP tools"| CC
BooChat -->|"streamText"| LLM
BooCoder -->|"native inference"| LLM
BooCoder -->|"ACP or PTY spawn"| Agents
Agents --> LLM
Three surfaces, one database
| Surface | Code | Runtime | Primary role |
|---|---|---|---|
| BooChat | apps/server + apps/web |
Docker | Read-only chat, file tools, MCP client, skills |
| BooTerm | apps/booterm + terminal panes in apps/web |
Docker | tmux + xterm.js PTY panes |
| BooCoder | apps/coder + CoderPane in apps/web |
Host systemd | Write tools, task queue, ACP/PTY agent dispatch |
All surfaces share Postgres (boochat DB). Cross-surface joins link chats, tasks, and sessions.
BooChat request path
sequenceDiagram
participant U as User
participant W as apps/web
participant S as apps/server
participant DB as Postgres
participant L as llama-swap
U->>W: POST message
W->>S: /api/sessions/:id/messages
S->>DB: user + assistant streaming rows
S->>S: inference.enqueue()
loop outer step loop
S->>L: streamText
L-->>S: deltas / tool calls
S->>W: WS frames via broker
opt tool calls
S->>S: executeToolPhase
S->>DB: message_parts
end
end
S->>DB: finalize message
S->>W: session_updated user frame
Key modules: services/inference/turn.ts (outer loop), stream-phase.ts (AI SDK adapter), tool-phase.ts, services/broker.ts, hooks/useSessionStream.ts.
BooCoder execution paths
flowchart LR
Msg["User message<br/>CoderPane"] --> Route{"provider?"}
Route -->|boocode| Inf["In-process inference<br/>pending_changes queue"]
Route -->|external| Task["tasks row<br/>dispatcher poll"]
Task --> ACP["ACP dispatch<br/>opencode goose"]
Task --> PTY["PTY dispatch<br/>claude qwen"]
ACP --> Host["spawn install_path<br/>on host"]
PTY --> Host
Inf --> Apply["apply_pending → disk"]
Since v2.1.0, BooCoder runs on the host (not Docker). Agent binaries spawn directly — no SSH tunnel.
Supporting services
| Service | Reachability | Purpose |
|---|---|---|
| codecontext | http://codecontext:8080 from Docker network |
Code graph / symbol analysis (Go sidecar) |
| llama-swap | LLAMA_SWAP_URL env |
Local LLM inference + model props |
| SearXNG | SEARXNG_URL (Tailscale Fathom) |
web_search / web_fetch when enabled |
| MCP servers | /data/mcp.json config |
Optional tools (e.g. Context7), read-only in BooChat |
Config and data files
| Path | Role |
|---|---|
data/AGENTS.md |
Global agent registry (bind-mounted /data/AGENTS.md) |
data/mcp.json |
MCP server config (opencode-compatible shape) |
data/skills/ |
On-demand skill library |
BOOCHAT.md / BOOCODER.md |
Container guidance (mtime-cached into system prompt) |
apps/server/src/schema.sql |
Canonical DB schema |
Deploy topology
- BooChat + BooTerm + Postgres + codecontext:
docker compose up --build -dfrom/opt/boocode - BooCoder:
pnpm -C apps/server build && pnpm -C apps/coder build && sudo systemctl restart boocoder - Ports bind to Tailscale IP
100.114.205.53, not0.0.0.0— use that IP for host smoke curls