v2.12.0 — Grilled to Perfection
Complete docs and backend audit. Streaming chat, hardened terminal, vault memory, and a system prompt driven by CLAUSE.md.
Browser-based AI coding harness with real PTY terminal, streaming LLM chat with native tool-calling, persistent code editor, and project memory vault.
┌──────────────────────────────────────────────────────────────┐
│ Browser │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ React + Vite frontend │ prototype.html (legacy) │ │
│ │ File tree, editor, chat, terminal, vault panels │ │
│ └────────────────────┬───────────────────────────────────┘ │
└───────────────────────┼───────────────────────────────────────┘
│ proxy.js (port 3001)
│ HTTP static + /api proxy + /terminal upgrade
▼
┌──────────────────────────────────────────────────────────────┐
│ Backend (port 3002) │
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
│ │ Chat Controller │ │ TerminalGateway │ │ Files API │ │
│ │ └─ SSE stream │ │ └─ Socket.IO WS │ │ └─ CRUD │ │
│ │ └─ Tool loop │ │ └─ node-pty │ │ │ │
│ │ └─ Vault memory │ │ └─ PTY reset/ │ │ │ │
│ │ └─ Tree context │ │ reconnect │ │ │ │
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
│ │ Session Store │ │ Settings API │ │ Model Gateway│ │
│ │ └─ In-memory │ │ └─ Provider cfg │ │ └─ Routing │ │
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
│ │ Git Controller │ │ Project API │ │ Vault API │ │
│ │ └─ Status/branch│ │ └─ Discovery │ │ └─ Notes/CAG │ │
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
│ ┌─────────────────┐ │
│ │ Workspace API │ ── compact file-tree summaries │
│ └─────────────────┘ │
└──────────────────────────────────────────────────────────────┘
React 19 + Vite application in apps/frontend/:
- File tree sidebar
- Slide-in editor with syntax highlighting (TSX, Python, Rust, Go, Shell, YAML, TOML, CSV, Markdown, SQL, JSON, Dockerfile, dotenv)
- Collapsible terminal panel with persistent PTY tabs
- Streaming chat panel with tool-call cards
- Vault panel for project memory (gbrain-style notes)
- Workspace selector with recent-workspace persistence
- Web apps auto-discovery panel
- Spreadsheet viewer (CSV/XLSX)
- Settings panel (provider/model configuration)
- Always-dark editor regardless of theme mode
prototype.html remains in the repo as the original single-file reference but is no longer the primary runtime UI.
NestJS monolith at apps/backend/src/. Module structure:
| Module | Endpoint | Function |
|---|---|---|
chat |
POST /api/chat, POST /api/chat/stream |
SSE streaming, multi-turn tool loop, vault + tree context |
terminal |
WS /terminal |
node-pty over Socket.IO with reset/reconnect lifecycle |
tools |
Internal | bash, read_file, write_file, grep, list_files |
sessions |
GET/POST/DELETE /api/sessions |
Chat session CRUD |
settings |
GET/PUT /api/settings |
Provider/model configuration |
files |
GET/POST/PUT/DELETE /api/files |
Workspace file operations |
git |
GET /api/git/* |
Status, branch, log |
project |
GET /api/project/apps |
Web app discovery |
vault |
GET/POST/PUT/DELETE /api/vault/* |
Project memory notes + context ranking |
workspace |
GET /api/workspaces/tree |
Compact file-tree summary |
model-gateway |
POST /api/model-gateway/* |
LLM API routing |
model-routing |
Internal | Model selection logic |
searxng-search |
Internal | SearXNG integration |
filesystem |
Internal | FS abstractions |
tool-registry |
Internal | Tool schema and discovery |
agent-orchestrator |
Internal | Agent coordination |
cloak-browser |
Internal | Headless browser automation (Puppeteer) |
proxy.js — Node.js HTTP server on port 3001:
- Static file serving for the built React app (dist)
- WebSocket upgrade to backend port 3002 (
/terminalnamespace) - HTTP proxy for
/api/*routes to port 3002 - CORS preflight handling
- User types in terminal → xterm.js
onData→ Socket.IOterminal:input→ node-pty → shell process → PTY output → Socket.IOterminal:data→ xterm.js write - User sends chat message →
POST /api/chat/stream(SSE) → system prompt (CLAUSE.md + harness + workspace tree + vault context) → LLM API → Server-Sent Events response → tool call parsed → tool executed → result appended → loop until completion - File open →
GET /api/files?path=→ file content → rendered in Monaco editor - Tool execution (from chat) →
tools.service.ts→list_files,read_file,write_file,grep,bash→ result serialized to SSE stream - Vault note created/updated during chat → persisted to
.cammander/vault/and indexed for future context retrieval
- Node.js >= 20
- npm >= 10
- Unix shell (Bash or Zsh) for PTY terminal
- OS: macOS, Linux, Windows (WSL2)
@nestjs/common/@nestjs/core/@nestjs/platform-express^11.0.0@nestjs/platform-socket.io/@nestjs/websockets^11.0.0@nestjs/config^4.0.0socket.io^4.8.0node-pty^1.0.0simple-git^3.27.0puppeteer^24.0.0 + pluginsuuid^11.0.0axios^1.7.0ws^8.18.0marked,highlight.js,dompurify(frontend)
react^19.1.0 /react-dom^19.1.0@xterm/xterm^6.0.0 +@xterm/addon-fit^0.11.0 +@xterm/addon-web-links^0.12.0socket.io-client^4.8.3@monaco-editor/react^4.7.0xlsx^0.18.5marked^15.xhighlight.js^11.xdompurify^3.x
Stored in <DATA_DIR>/settings.json:
{
"activeProvider": "ollama-local",
"ollamaLocal": {
"host": "localhost",
"port": 11434
},
"defaultModel": "qwen2.5-coder:14b"
}Supported providers: ollama-local, ollama-cloud, openai-compat, llama-cpp, vllm, lm-studio.
Ollama Cloud endpoint must use https://ollama.com/v1. https://api.ollama.com returns a 301 redirect that drops the Authorization header.
Optional .env in apps/backend/:
PORT=3002
FRONTEND_PORT=3001
OLLAMA_CLOUD_API_KEY=sk-...
OLLAMA_CLOUD_BASE_URL=https://ollama.com/v1
OLLAMA_CLOUD_DEFAULT_MODEL=deepseek-v4-flash
DEFAULT_WORKSPACE=/home/user/projects
cammander auto-discovers and loads system prompts from the workspace root, in priority order:
CLAUSE.mdHQ.mdAGENTS.mdsoul.md
CLAUSE.md is the canonical project harness. It carries behavioral guidelines and is intentionally named to signal independence from any single provider's brand. Loaded by chat.controller.ts and combined with a Cammander Coding Harness, workspace tree summary, vault context, and project layout before each LLM call.
# Root dependencies
npm install
# Full build (shared + backend + frontend)
npm run build
# Backend only
npm run build:backend
# Frontend only
npm run build:frontend
# Tests
npm run test# Terminal 1: Backend
cd apps/backend && PORT=3002 node dist/apps/backend/src/main.js
# Terminal 2: Proxy
cd /path/to/cammander
node proxy.js
# Access
open http://localhost:3001Alternative: node proxy.js in background, then PORT=3002 node apps/backend/dist/apps/backend/src/main.js.
cammander/
├── prototype.html Legacy single-file reference
├── proxy.js HTTP + WS proxy (port 3001 → 3002)
├── new-features.css Incremental UI patches
├── HQ.md Project system prompt
├── CLAUSE.md Canonical coding-harness guidelines
├── manifest.json PWA manifest
├── package.json Root workspace (npm workspaces)
├── CHANGELOG.md Release notes
├── docs/
│ └── plans/ Implementation plans
├── apps/
│ ├── backend/
│ │ ├── src/
│ │ │ ├── main.ts
│ │ │ ├── app.module.ts
│ │ │ ├── modules/
│ │ │ │ ├── chat/
│ │ │ │ ├── terminal/
│ │ │ │ ├── tools/
│ │ │ │ ├── sessions/
│ │ │ │ ├── settings/
│ │ │ │ ├── files/
│ │ │ │ ├── git/
│ │ │ │ ├── project/
│ │ │ │ ├── vault/
│ │ │ │ ├── workspace/
│ │ │ │ ├── model-gateway/
│ │ │ │ ├── model-routing/
│ │ │ │ ├── searxng-search/
│ │ │ │ ├── filesystem/
│ │ │ │ ├── tool-registry/
│ │ │ │ ├── agent-orchestrator/
│ │ │ │ └── cloak-browser/
│ │ │ └── gateway/
│ │ └── dist/ Compiled output
│ └── frontend/
│ ├── src/
│ │ ├── components/
│ │ │ ├── ChatPanel.tsx
│ │ │ ├── TerminalPanel.tsx
│ │ │ ├── VaultPanel.tsx
│ │ │ ├── WorkspaceSelector.tsx
│ │ │ ├── FileTree.tsx
│ │ │ ├── EditorTabs.tsx
│ │ │ ├── EditorPane.tsx
│ │ │ ├── WebAppsPanel.tsx
│ │ │ └── SpreadsheetViewer.tsx
│ │ ├── stores/
│ │ ├── hooks/
│ │ └── utils/
│ │ └── renderMarkdown.ts
│ └── vite.config.ts
├── shared/
│ └── tsconfig.json
└── assets/
├── logo-32.png
├── logo-64.png
├── logo-128.png
├── apple-touch-icon.png
├── icon-192.png
└── icon-512.png
| Method | Path | Description |
|---|---|---|
| POST | /api/chat |
Non-streaming chat (kept for compatibility) |
| POST | /api/chat/stream |
SSE streaming chat, accepts { message, sessionId?, model?, workspaceRoot? } |
| Method | Path | Description |
|---|---|---|
| GET | /api/sessions |
List all sessions |
| POST | /api/sessions |
Create session { title } |
| DELETE | /api/sessions/:id |
Delete session |
| Method | Path | Description |
|---|---|---|
| GET | /api/files?path= |
Read file |
| POST | /api/files |
Create { path, content } |
| PUT | /api/files |
Update { path, content } |
| DELETE | /api/files?path= |
Delete |
| Method | Path | Description |
|---|---|---|
| GET | /api/settings |
Read settings |
| PUT | /api/settings |
Update settings |
| Method | Path | Description |
|---|---|---|
| GET | /api/git/status |
Working tree status |
| GET | /api/git/branch |
Current branch |
| GET | /api/git/log |
Recent commits |
| Method | Path | Description |
|---|---|---|
| GET | /api/vault/notes |
List notes |
| POST | /api/vault/notes |
Create note |
| PUT | /api/vault/notes/:id |
Update note |
| DELETE | /api/vault/notes/:id |
Delete note |
| POST | /api/vault/context |
Rank relevant notes for a query |
| Method | Path | Description |
|---|---|---|
| GET | /api/workspaces |
List saved workspaces |
| GET | /api/workspaces/home-folders?base= |
Scan a directory for project folders |
| GET | /api/workspaces/tree?path= |
Compact ASCII file-tree summary |
| GET | /api/workspaces/browse?path= |
Browse directory entries |
| Method | Path | Description |
|---|---|---|
| GET | /api/project/apps |
Auto-detected + configured web apps |
Namespace: /terminal
| Event | Direction | Payload | Description |
|---|---|---|---|
terminal:attach |
Client → Server | { slot?, cwd?, cols?, rows? } |
Attach to or spawn PTY session |
terminal:create |
Client → Server | { cwd?, cols?, rows? } |
Legacy spawn (default slot) |
terminal:input |
Client → Server | { data: string } |
STDIN input |
terminal:resize |
Client → Server | { cols, rows } |
Resize PTY |
terminal:kill |
Client → Server | { slot? } |
Kill PTY |
terminal:reset |
Client → Server | { slot? } |
Kill and clear PTY slot |
terminal:data |
Server → Client | { data: string } |
STDOUT/STDERR output |
terminal:exit |
Server → Client | { exitCode: number } |
Process exit |
terminal:ready |
Server → Client | { cwd, pid, slot, reattached } |
PTY ready |
terminal:reset |
Server → Client | {} |
PTY was reset |
terminal:slots |
Server → Client | { slots: string[] } |
Active session IDs |
This release is the result of a full /grill-check docs-and-code audit. See CHANGELOG.md for the complete list of changes.
Highlights:
- Streaming chat via
/api/chat/streamreplaces the synchronous endpoint as the primary UX. - Workspace file-tree summary is injected into every chat system prompt.
CLAUSE.mdis the canonical project soul file.- Vault notes are validated, context-ranked, and covered by tests.
- Terminal PTY supports reset, reconnect, and explicit cleanup.
- Default provider is now
ollama-localfor local-first use. - Markdown rendering uses
marked+highlight.js+dompurify. - Backend tests exist for
ToolsServiceandVaultService. - Dead
SessionModuleremoved;SessionsModuleis the single session source of truth.
MIT — Copyright (c) 2026 Guideboard Labs
