feat: MCP {env:VAR} key substitution + coder model/tool-result fixes + docs refactor (v2.7.9)
- MCP secrets: substituteEnvVars recursively resolves {env:NAME} in mcp.json string values from process.env before Zod (opencode-compatible); unset -> '' + boot warning, and invalid-config log names the unset vars (an empty {env:VAR} in a strict url/command field invalidates the whole config)
- data/mcp.json now untracked (.gitignore flips !data/mcp.json -> !data/mcp.example.json); tracked template data/mcp.example.json carries "{env:CONTEXT7_API_KEY}"; .env.example documents the key (9 mcp-config tests)
- Coder fix: message_complete frame model widened string -> string|null (server+web ws-frames parity); dispatcher publishes model: task.model at all 4 external completion points — a null model otherwise fail-closed in publishFrame and dropped the whole frame incl. status:'complete' (regression test)
- Coder fix: claude-sdk mapUserToolResults maps user-message tool_result blocks -> terminal tool_update events (completed/failed w/ output) so tool snapshots resolve instead of spinning forever
- Composer: AgentComposerBar drops §9b resumed/history/new chip + token readout, loses flex-wrap so the row stays one line; CoderPane gains a per-chat localStorage agent-config cache (restores last model on reopen) + threads model into the timeline/chip
- Docs: root CLAUDE.md slimmed (~190 lines), per-app refs split to apps/{coder,server,web}/CLAUDE.md; new docs/coder-backends.md, docs/project-discovery.md, docs/coding-standards/ (cross-app-contract-parity); ARCHITECTURE.md links the backends doc
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
132
docs/project-discovery.md
Normal file
132
docs/project-discovery.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# Project Discovery
|
||||
|
||||
> Auto-generated stack / tooling / command inventory for the BooCode repository. Static reference for skills, agents, and contributors. Deep engineering notes live in the root and per-app `CLAUDE.md` files; this file is the factual "what's installed and how to run it" map.
|
||||
|
||||
## Repository
|
||||
|
||||
- type: pnpm monorepo (workspaces `apps/*` + `apps/coder/web`)
|
||||
- package manager: pnpm 10.15.1 (root `package.json` `packageManager`)
|
||||
- lock file: `pnpm-lock.yaml`
|
||||
- workspace config: `pnpm-workspace.yaml`
|
||||
- shared TS config: `tsconfig.base.json` (ES2022 target, strict, `noUncheckedIndexedAccess`, `isolatedModules`)
|
||||
- languages: TypeScript (all Node packages), Go 1.24 (codecontext sidecar)
|
||||
- database: PostgreSQL 16 (single `boochat` DB; two schema files applied idempotently — `apps/server/src/schema.sql` + `apps/coder/src/schema.sql`)
|
||||
- members: 5 Node packages (`@boocode/server`, `@boocode/web`, `@boocode/coder`, `@boocode/coder-web`, `@boocode/booterm`) + 1 Go sidecar (`codecontext/`)
|
||||
- cross-workspace dep: `@boocode/coder` → `@boocode/server` (`workspace:*`); **server must build first** (emits `.d.ts` for consumers)
|
||||
- build order: server → coder → web/booterm (independent) → codecontext (Docker, Go)
|
||||
|
||||
## Repository-level
|
||||
|
||||
### Documentation
|
||||
|
||||
- primary guidance: `CLAUDE.md` (root, tracked) + per-app `apps/server/CLAUDE.md`, `apps/coder/CLAUDE.md`, `apps/web/CLAUDE.md` (lazy-loaded per subtree)
|
||||
- overview: `README.md`
|
||||
- release log: `CHANGELOG.md` (per-tag, newest-first)
|
||||
- system prompts: `BOOCHAT.md`, `BOOCODER.md` (bind-mounted into containers)
|
||||
- architecture: `docs/ARCHITECTURE.md` (system diagram + overview)
|
||||
- planning docs: `docs/codecontext-ts-plan.md`, `docs/DEFERRED-WORK.md`, `docs/STALE-DEPRECATED.md`, `docs/themes_v1.md`, `docs/superpowers/plans/`
|
||||
- specs/design: `openspec/README.md` (convention) + `openspec/changes/<slug>/{proposal,tasks,design}.md`; shipped batches snapshot under `openspec/changes/archived/`
|
||||
|
||||
### Agent registry & skills
|
||||
|
||||
- agent registry: `data/AGENTS.md` (tracked; parsed — each `## <Name>` + `---` frontmatter fence is one agent)
|
||||
- skills: `data/skills/<vendor>/` (each skill = `SKILL.md` + optional `eval.yaml`); vendors include `boocode/` (`committing-changes`, `improving-boocode-guidance`, `systematic-debugging`, `using-worktrees`), `anthropics/`, `superpowers/`, `mattpocock/`, others
|
||||
|
||||
### Infrastructure
|
||||
|
||||
- container build: `Dockerfile` (root — boocode = server + web; `node:20-alpine` builder + runtime; runtime adds ripgrep/git/ssh)
|
||||
- container build: `apps/booterm/Dockerfile` (`node:20-alpine` builder → `node:20-bookworm-slim` runtime for node-pty libc parity)
|
||||
- container build: `codecontext/Dockerfile` (`golang:1.24-alpine` → `alpine:3.20`)
|
||||
- container build: `apps/coder/Dockerfile` (present but unused — BooCoder now runs via host systemd, not Docker)
|
||||
- orchestration: `docker-compose.yml` — services `boocode` (:9500), `booterm` (:9501), `boocode_db` (postgres:16-alpine, host :5500), `codecontext` (internal :8080); `boocoder` service commented out (moved to host systemd `boocoder.service`, :9502)
|
||||
- CI/CD: none in repo (`.github/workflows`, `.gitea`, `.gitlab-ci.yml` absent); deploy is manual (`docker compose up --build -d`; boocoder via `pnpm build` + `sudo systemctl restart boocoder`)
|
||||
- git hooks: none committed (`.git/hooks/` has only `.sample`); a host-side `security_reminder_hook.py` is referenced but not in-repo
|
||||
- ADRs: no dedicated directory; decisions live inline in `CLAUDE.md` files, `docs/ARCHITECTURE.md`, and `openspec/changes/*/design.md`
|
||||
- linters/formatters: none configured (no eslint/prettier/stylelint config)
|
||||
|
||||
### Environment & configuration
|
||||
|
||||
- env file: `.env` (gitignored) / `.env.example` (tracked template)
|
||||
- boocoder host env: `apps/coder/.env.host`
|
||||
- config template: `data/mcp.example.json` (tracked) — live `data/mcp.json` is gitignored; secrets live in `.env` and resolve via `{env:VAR}` substitution (e.g. `CONTEXT7_API_KEY`)
|
||||
- config template: `data/coder-providers.example.json` (tracked) — live `data/coder-providers.json` is gitignored (runtime, read+written on UI toggles)
|
||||
|
||||
## Projects
|
||||
|
||||
### `boocode` (root coordinator) — `/`
|
||||
|
||||
- manifest: `package.json`
|
||||
- role: pnpm workspace root; coordinates dev/build across members
|
||||
- install: `pnpm install`
|
||||
- dev: `pnpm dev:server` (tsx watch, :3000), `pnpm dev:web` (Vite, :5173)
|
||||
- build: `pnpm build` (web then server)
|
||||
- start: `pnpm start` (`node apps/server/dist/index.js`)
|
||||
- typecheck: `npx tsc --noEmit` (project references; per-app `tsc` is authoritative)
|
||||
|
||||
### `@boocode/server` — `apps/server/`
|
||||
|
||||
- manifest: `apps/server/package.json`
|
||||
- runtime: Node.js + TypeScript
|
||||
- frameworks: Fastify ^4.28.1 (+ `@fastify/websocket` ^10, `@fastify/static` ^7); postgres ^3.4.4 (porsager, tagged-template SQL, no ORM); Vercel AI SDK — `ai` ^6 + `@ai-sdk/openai-compatible` ^2 (llama-swap); Zod ^3; `@modelcontextprotocol/sdk` ^1.29
|
||||
- build: `pnpm -C apps/server build` (`tsc` + copy `schema.sql` → `dist/`) — authoritative for server code
|
||||
- dev: `pnpm -C apps/server dev` (tsx watch)
|
||||
- typecheck: `pnpm -C apps/server typecheck`
|
||||
- test: `pnpm -C apps/server test` (vitest run)
|
||||
- tsconfig: `apps/server/tsconfig.json` (NodeNext, `declaration: true` for workspace consumers; `exports` map with `types` conditions)
|
||||
- test config: `apps/server/vitest.config.ts` (vitest ^3.2.4, env=node, `globals: false`, `fileParallelism: false`)
|
||||
- test pattern: `src/**/__tests__/**/*.test.ts`
|
||||
- DB-integration tests: opt-in via `DATABASE_URL='postgres://boocode:devpass@localhost:5500/boochat' pnpm -C apps/server test`
|
||||
|
||||
### `@boocode/web` — `apps/web/`
|
||||
|
||||
- manifest: `apps/web/package.json`
|
||||
- runtime: Node.js + TypeScript (browser SPA; also hosts the BooCoder pane)
|
||||
- frameworks: React ^18.3.1 + React DOM; React Router v6.26.0; Tailwind v4.3.0 (+ `@tailwindcss/postcss`); shadcn/radix-ui primitives; Shiki ^1.29 (highlighting); `@xterm/xterm` 5.5 (+ addons fit/web-links/webgl); Vite ^5.3.4 (+ `@vitejs/plugin-react`)
|
||||
- build: `pnpm -C apps/web build` (`tsc -b` + `vite build`)
|
||||
- dev: `pnpm -C apps/web dev` (Vite, :5173)
|
||||
- preview: `pnpm -C apps/web preview`
|
||||
- typecheck: `pnpm -C apps/web typecheck` (`tsc -b --noEmit`) — or `npx tsc -p apps/web/tsconfig.app.json --noEmit`
|
||||
- tests: none (no test harness by design)
|
||||
- tsconfig: `apps/web/tsconfig.json` (composite refs) + `apps/web/tsconfig.app.json` (Bundler resolution, `react-jsx`, path alias `@/` → `src/*`)
|
||||
- dev config: `apps/web/vite.config.ts` (proxy order: `/api/term` + `/ws/term` → :9501, `/api/coder` → :9502, `/api` → :3000)
|
||||
|
||||
### `@boocode/coder` — `apps/coder/`
|
||||
|
||||
- manifest: `apps/coder/package.json`
|
||||
- runtime: Node.js + TypeScript; runs as host systemd service (`boocoder.service`, :9502), postgres at `127.0.0.1:5500`
|
||||
- frameworks: Fastify ^4.28.1 (+ `@fastify/websocket`); postgres ^3.4.4; agent SDKs — `@agentclientprotocol/sdk` ^0.22, `@anthropic-ai/claude-agent-sdk` ^0.3, `@opencode-ai/sdk` ~1.15 (imported via `@opencode-ai/sdk/v2/client`); `@modelcontextprotocol/sdk` ^1.29; `@boocode/server` (`workspace:*`)
|
||||
- build: `pnpm -C apps/coder build` (`tsc` + copy `schema.sql`) — requires server built first
|
||||
- dev: `pnpm -C apps/coder dev` (tsx watch)
|
||||
- cli: `pnpm -C apps/coder cli` (`tsx src/cli.ts`)
|
||||
- typecheck: `pnpm -C apps/coder typecheck`
|
||||
- test: `pnpm -C apps/coder test` (vitest run)
|
||||
- deploy: `pnpm -C apps/server build && pnpm -C apps/coder build && sudo systemctl restart boocoder`
|
||||
- tsconfig: `apps/coder/tsconfig.json` (NodeNext, `declaration: false`)
|
||||
- test config: `apps/coder/vitest.config.ts` (vitest ^3.0.0, env=node, `globals: false`, `fileParallelism: false`)
|
||||
- test pattern: `src/**/__tests__/**/*.test.ts`
|
||||
|
||||
### `@boocode/coder-web` — `apps/coder/web/`
|
||||
|
||||
- manifest: `apps/coder/web/package.json`
|
||||
- runtime: Node.js + TypeScript; standalone fallback SPA served at :9502 (primary coder UI is the pane in `@boocode/web`)
|
||||
- frameworks: React ^18.3.1 + React Router v6.26.0 + Tailwind v4.3.0 + Vite ^5.3.4
|
||||
- dev config: `apps/coder/web/vite.config.ts` (port 5174; proxies `/api` → `http://127.0.0.1:3000`)
|
||||
|
||||
### `@boocode/booterm` — `apps/booterm/`
|
||||
|
||||
- manifest: `apps/booterm/package.json`
|
||||
- runtime: Node.js + TypeScript; Docker container (:9501, bookworm-slim+glibc)
|
||||
- frameworks: Fastify ^4.28.1 (+ `@fastify/websocket`); node-pty ^1.0.0; `pg` ^8.13 (session persistence); tmux (per-session `bc-<sid>`)
|
||||
- build: `pnpm -C apps/booterm build` (`tsc` only)
|
||||
- dev: `pnpm -C apps/booterm dev` (tsx watch)
|
||||
- typecheck: `pnpm -C apps/booterm typecheck`
|
||||
- tests: none
|
||||
- tsconfig: `apps/booterm/tsconfig.json` (NodeNext, `declaration: false`)
|
||||
|
||||
### codecontext shim — `codecontext/`
|
||||
|
||||
- manifest: `codecontext/go.mod`
|
||||
- runtime: Go 1.24; standalone binary, MCP stdio↔HTTP adapter (NDJSON framing); Docker sidecar at `http://codecontext:8080/v1/<tool_name>`
|
||||
- source: single `shim.go`; wraps the CodeContext fork staged via `codecontext/fork.tar.gz` (gitignored; fork repo at `/opt/forks/codecontext/`, branch `boocode-ts`)
|
||||
- build: `go build ./...` (use `/snap/go/current/bin/go`); built into the container in Docker
|
||||
- test: `go test ./...`
|
||||
Reference in New Issue
Block a user