indifferentketchup e30a9e8b23 feat(coder): v2.6 Phase 1 — OpenCode warm server backend
Persistent multi-turn opencode backend: one `opencode serve` HTTP server per
BooCoder process, one opencode session per BooCode session (resumed on
switch-back), single SSE read loop demuxed by session id.

- backends/opencode-server.ts: AgentBackend implementation — spawn with
  waitForReady, session.next.* SSE event translation (text/reasoning/tool
  deltas), Paseo-ported reasoning dedup (streamedPartKeys), promptAsync
  fire-and-forget settled by session.idle, per-turn inactivity watchdog
  (180s) + reconnect reconciliation via session.messages, stale-session
  guard (crashed-not-resumed + config_hash fingerprint on model).
- dispatcher.ts: opencode routes to pool backend (ensureSession→prompt);
  per-session concurrency Map replaces global running boolean (1.9);
  model coalesce (empty→DEFAULT_MODEL) + llama-swap/ prefix for opencode;
  diff-supersede (DELETE+INSERT pending_changes by session, stamp agent).
- worktrees.ts: ensureSessionWorktree (session-keyed, captures base_commit,
  persists to session_worktrees); diffWorktree gains optional baseRef.
- agent-probe.ts: mergeLlamaSwap branch fetches /v1/models, prefixes with
  llama-swap/, populates opencode's available_agents.models (was 0).
- provider-snapshot.ts: export fetchLlamaSwapModels for probe reuse.
- schema.sql: session_worktrees + agent_sessions tables (Phase 0) +
  config_hash column on agent_sessions, pending_changes.agent column.
- package.json: @opencode-ai/sdk ~1.15.0 (resolved 1.15.12).

Known Phase 1 limitation: single SSE stream scoped to most-recent session's
directory; concurrent opencode sessions in different worktrees collide
(warning logged, watchdog prevents hang). Phase 2 moves to per-session SSE.

Smoke 1 verified: two turns in one session, both produce real tokens, same
agent_session_id reused, same server port, turn 2 is 9x faster (no spawn).
goose/qwen/claude paths untouched (runExternalAgent md5 identical).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 20:37:11 +00:00
2026-05-26 23:29:25 +00:00
2026-05-26 23:29:25 +00:00
2026-05-14 19:24:50 +00:00

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 tools
  • apps/web — React frontend; served by Fastify in production, Vite in dev
  • apps/booterm — Fastify + node-pty + tmux for in-browser terminal panes
  • apps/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). See CURRENT.md.
Description
No description provided
Readme AGPL-3.0 7.7 MiB
Languages
TypeScript 94.1%
CSS 1.9%
JavaScript 1.2%
Shell 0.8%
Go 0.6%
Other 1.4%