0a86dfb8c5
A new **AI Router** tab in Settings, next to Codex, stores named router
endpoints (9Router, OpenRouter, a self-hosted gateway) as profiles: a base
URL, an API key, a default model and an optional per-tier override. The tab
only stores them; a lane CHOOSES one in the Add-lane modal, via a Native /
AI Router radio, and that choice is written into the lane's own config.
The two CLIs are configured differently, and the difference is theirs:
- a claude lane gets eight `env` keys merged into its own
`.claude/settings.local.json` (`.local` because the value holds a key);
- a codex lane gets `$CODEX_HOME/<name>.config.toml` — the layer
`codex -p <name>` loads — because Codex has NO project-level config.
Its base `config.toml` is never touched.
Native is a built-in profile rather than a code branch, so "go back to
native" is the same write path. It blanks the two connection variables
instead of removing them (an absent key at project scope lets a USER-level
router apply) and removes the model names instead of writing them (writing
them would override the user's own global model choice).
Key material never leaves the server: profiles live one file each under
`<CLAUDE_HOME>/agenthub-routers/` (0700/0600), `GET /api/ai-routers`
reports only `hasKey`, and there is deliberately no route returning one
profile in full.
Three things this had to get right, each found by review and verified
against the real tools rather than assumed:
- `wire_api = "chat"` is rejected outright by codex-cli 0.149 ("no longer
supported"), so every codex lane on a router would have failed to start.
The layer writes "responses", and writes `env_key` only when the profile
actually has a key — naming an unset variable is itself a startup error.
- The key must never be TYPED into a pane. `tmux.sendCommand` used
`send-keys` with a `KEY='…' cmd` prefix, which the dashboard streams to
every attached browser and bash appends to history; it now takes over the
idle pane with `respawn-pane -k -e`, passing env through argv the way
`newSession` always has. Verified on tmux 3.4: multi-element argv arrives
intact and the pane renders no trace of the value.
- Attaching COPIES a profile, so editing or deleting one in Settings has to
reach the lanes already using it. An edit re-applies it (a rotated key
would otherwise never reach the lane still holding the revoked one); a
delete resets those lanes to native and removes the Codex layer file.
Both report per-lane failures, which the tab surfaces.
`.claude/settings.local.json` is added to the lane's git exclude, for both
native and router lanes: `agenthub lanes reset` runs `git clean -fd` without
`-x`, so an un-excluded settings file is deleted on reset — and untracked
meant the key was committable.
DB: `lanes.router_profile`, nullable, additive. Written only by
`setRouterProfile` beside the disk write, never through `PATCHABLE`.
Documentation Index
Comprehensive documentation for the Agent Dashboard project.
Quick Links
- Architecture Overview - System design and technical reference
- I18N Architecture - Internationalization architecture and usage guide
- CLI Reference - The
agenthubterminal CLI: every command, discovery, safety model - Setup Guide - Installation and configuration
- Installation - Detailed installation instructions
Documentation Sections
📘 Core Documentation
graph TB
Start[Start Here] --> Setup[SETUP.md<br/>Installation & Config]
Start --> Architecture[ARCHITECTURE.md<br/>System Design]
Setup --> Client[Client README<br/>React UI docs]
Setup --> Server[Server README<br/>Backend docs]
Architecture --> API[API.md<br/>REST & WebSocket]
Architecture --> Database[DATABASE.md<br/>Schema reference]
Architecture --> Hooks[HOOKS.md<br/>Hook system integration]
Architecture --> MCP[MCP.md<br/>MCP server integration]
style Start fill:#3B82F6
style Setup fill:#10B981
style Architecture fill:#F59E0B
📋 Documentation Catalog
| Document | Description | Audience |
|---|---|---|
| client/README.md | React frontend architecture, components, state management | Frontend developers |
| server/README.md | Express backend, database, WebSocket, API | Backend developers |
| API.md | REST API endpoints (sessions, agents, events, stats, analytics, hooks, pricing, workflows, settings, import history, cc-config, run), WebSocket protocol (including run_stream / run_status / run_input_ack for the Run page) |
Integration developers |
| DATABASE.md | SQLite schema, queries, performance | Database administrators |
| HOOKS.md | Claude Code hook system integration | Hook developers |
| MCP.md | MCP server setup and tool reference | MCP integrators |
| I18N.md | Language architecture, locale strategy, and rollout checklist | Frontend and product teams |
| CLI.md | agenthub command reference — monitoring, browsing, insights, alerts, pricing, import, administration |
Terminal users and CI scripting |
Getting Started
For New Users
graph LR
A[New to Project] --> B[Read SETUP.md]
B --> C[Install Dependencies]
C --> D[Run npm run dev]
D --> E[Open localhost:5173]
style A fill:#3B82F6
style E fill:#10B981
Quick Start:
- Install the system packages —
node(20+),git, andtmux(the run console has no fallback without it): INSTALL.md → Step 0 - Read SETUP.md
- Run
npm run setup - Run
npm run dev - Open browser to
http://localhost:5173
For Frontend Developers
graph TB
FE[Frontend Developer] --> ClientDocs[client/README.md]
ClientDocs --> Components[Component Architecture]
ClientDocs --> State[State Management]
ClientDocs --> WebSocket[WebSocket Integration]
style FE fill:#61DAFB
Key Documents:
- client/README.md - Complete frontend guide
- API.md - WebSocket protocol
- Component source:
client/src/components/
For Backend Developers
graph TB
BE[Backend Developer] --> ServerDocs[server/README.md]
ServerDocs --> Routes[API Routes]
ServerDocs --> DB[Database Design]
ServerDocs --> WS[WebSocket Server]
style BE fill:#339933
Key Documents:
- server/README.md - Complete backend guide
- DATABASE.md - Schema and queries
- HOOKS.md - Hook processing
- API source:
server/routes/
For Integration Developers
graph TB
Integration[Integration Developer] --> API[API.md]
API --> REST[REST Endpoints]
API --> WebSocket[WebSocket Events]
Integration --> MCP[MCP.md]
MCP --> Tools[MCP Tools]
MCP --> Config[Client Configuration]
style Integration fill:#8B5CF6
Key Documents:
Architecture Overview
System Components
graph TB
subgraph "Frontend"
React[React + TypeScript<br/>Vite + Tailwind]
end
subgraph "Backend"
Express[Express Server<br/>Node.js 20+]
DB[(SQLite Database)]
WS[WebSocket Server]
end
subgraph "Integration"
Hooks[Claude Code Hooks]
MCP[MCP Server]
end
subgraph "Clients"
Browser[Web Browser]
Claude[Claude Desktop]
Custom[Custom Clients]
end
Browser --> React
React -->|HTTP/WS| Express
Express --> DB
Express --> WS
Hooks -->|HTTP POST| Express
Claude -->|stdio| MCP
MCP -->|HTTP| Express
Custom -->|HTTP| Express
style React fill:#61DAFB
style Express fill:#000000,color:#fff
style DB fill:#003B57,color:#fff
style MCP fill:#0f766e
Technology Stack:
| Layer | Technology |
|---|---|
| Frontend | React 18, TypeScript 5.7, Vite 6, Tailwind CSS |
| Backend | Node.js 20+, Express 4.21, WebSocket |
| Database | SQLite 3 (better-sqlite3 or node:sqlite) |
| Integration | Claude Code Hooks, MCP Server |
Internationalization Support (en/zh/vi/ko)
flowchart LR
A["User language preference<br/>en / zh / vi / ko"] --> B["i18next detector<br/>localStorage + navigator"]
B --> C["Namespace JSON resources"]
C --> D["React useTranslation hooks"]
D --> E["Localized UI + a11y labels"]
E --> F["Locale-aware date/number formatting"]
F --> G["formatModelName() — human-friendly model display"]
Supported language codes are explicitly en, zh, and vi. Use I18N.md for architecture details, naming conventions, language switching flow, localization behavior, and rollout guidance.
Feature Documentation
Real-Time Updates
sequenceDiagram
participant Hook as Claude Code Hook
participant Server as Dashboard Server
participant DB as SQLite
participant WS as WebSocket
participant Client as Browser
Hook->>Server: POST /hooks/post-tool-use
Server->>DB: Update data
DB-->>Server: Success
Server->>WS: Broadcast event
WS->>Client: { type: 'tool.executed', data }
Client->>Client: Update UI
Note over Client: No polling required!
Documentation:
Pricing System
graph TB
Model[Model Name] --> Match[Pattern Matching]
Match --> Custom{Custom<br/>Rule?}
Custom -->|Yes| UseCustom[Use Custom Pricing]
Custom -->|No| UseDefault[Use Default Pricing]
UseCustom --> Calculate[Calculate Cost]
UseDefault --> Calculate
Calculate --> Result[input_cost + output_cost]
style Calculate fill:#10B981
Documentation:
Hook System
graph LR
Claude[Claude Code] -->|stdin| Hook[Hook Script]
Hook -->|exec| Handler[hook-handler.js]
Handler -->|HTTP POST| Server[Dashboard Server]
Server --> DB[(Database)]
Server --> WS[WebSocket]
style Hook fill:#F59E0B
style Handler fill:#10B981
Documentation:
API Documentation
REST API Summary
| Endpoint | Method | Description |
|---|---|---|
/api/sessions |
GET | List sessions |
/api/sessions/:id |
GET | Get session |
/api/sessions/:id/agents |
GET | List session agents |
/api/agents/:id |
GET | Get agent |
/api/agents/:id/tools |
GET | List agent tools |
/api/pricing |
GET | List pricing rules |
/api/pricing |
POST | Create pricing rule |
/api/pricing/:pattern |
DELETE | Delete pricing rule |
Full Reference: API.md
WebSocket Events
| Event Type | Triggered By |
|---|---|
session.created |
SessionStart hook |
session.updated |
Any session update |
agent.created |
New agent started |
agent.updated |
Agent status/cost change |
tool.executed |
Tool execution completed |
notification.received |
System notification |
Full Reference: API.md
Database Schema
Entity Relationships
erDiagram
sessions ||--o{ agents : "has many"
agents ||--o{ tool_executions : "has many"
sessions ||--o{ notifications : "has many"
sessions {
text session_id PK
text model
text status
real total_cost
datetime updated_at
}
agents {
text agent_id PK
text session_id FK
text agent_type
text status
text current_tool
int input_tokens
int output_tokens
real cost
}
Full Reference: DATABASE.md
Performance Metrics
Benchmarks
| Metric | Target | Actual |
|---|---|---|
| Hook processing | < 100ms | ~70ms |
| API response time | < 50ms | ~30ms |
| WebSocket latency | < 10ms | ~5ms |
| Database query | < 10ms | ~5ms |
| Session list (50) | < 20ms | ~10ms |
Optimization Details:
Contributing
Development Workflow
graph LR
Fork[Fork Repository] --> Clone[Clone Locally]
Clone --> Branch[Create Feature Branch]
Branch --> Code[Write Code]
Code --> Test[Run Tests]
Test --> Commit[Commit Changes]
Commit --> Push[Push to Fork]
Push --> PR[Create Pull Request]
style Fork fill:#3B82F6
style PR fill:#10B981
Before submitting:
- Run tests:
npm test(servernode --test+ client Vitest, including per-screen render snapshots — regenerate intentional UI changes withcd client && npx vitest run -u) - Check formatting:
npm run format:check - Build:
npm run build - Update docs if needed
Support & Resources
Getting Help
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: This folder
Additional Resources
- Claude Code Documentation
- Model Context Protocol (MCP)
- SQLite Documentation
- React Documentation
- Express Documentation
License
Internal SmartGift build — all rights reserved.
Summary
This documentation covers:
- ✅ Complete architecture - Frontend, backend, database, integrations
- ✅ API reference - REST endpoints, WebSocket events
- ✅ Deployment guides - PM2, systemd, cloud
- ✅ Performance tuning - Database, server, client optimizations
- ✅ Integration guides - Hooks, MCP, custom clients
- ✅ Internationalization - Language resources, switching flow, locale formatting, rollout checklist
- ✅ Development guides - Setup, testing, contributing
Start with: SETUP.md for installation, then explore specific areas based on your role.