Architecture - twamp22/BumbaClaude GitHub Wiki
Architecture
The Wrapper Principle
BumbaClaude is a wrapper, not a modification. It sits entirely outside Claude Code and communicates through three public interfaces:
+------------------+ tmux +------------------+
| | ----------------> | |
| BumbaClaude | filesystem | Claude Code |
| (dashboard) | <---------------- | (agents) |
| | Agent SDK | |
+------------------+ ----------------> +------------------+
Communication Interfaces
-
tmux sessions -- Spawns, monitors, and controls Claude Code processes
- Spawn new agents with custom working directories and model choices
- Capture terminal output in real-time
- Send input to agents (messages, interrupts)
- Kill sessions gracefully or forcefully
-
Filesystem state -- Reads JSON files from ~/.claude/
- Team configurations at
~/.claude/teams/{team-name}/config.json - Task mailbox at
~/.claude/tasks/{team-name}/ - Agent state and message delivery
- Team configurations at
-
Agent SDK (planned v0.2.0) -- Programmatic API for agent control
- Cleaner agent spawning with explicit permissions
- Better model tier selection
- Advanced governance enforcement
Architecture Boundary
BumbaClaude NEVER:
- Modifies files under ~/.claude/ (read-only access only)
- Patches Claude Code's source or binary
- Spoofs client headers or OAuth tokens
- Bypasses rate limits or usage metering
This boundary is critical for maintainability and compliance. If a feature requires breaking this boundary, it's out of scope.
Tech Stack
| Layer | Technology | Purpose |
|---|---|---|
| Desktop | Electron 41+ | Windows app with tray, notifications, auto-update |
| Framework | Next.js 16+ | Server-rendered React with App Router |
| Language | TypeScript | Type-safe backend and frontend |
| Styling | Tailwind CSS | Dark mode primary, utility-first design |
| Database | SQLite via better-sqlite3 | Lightweight local storage, zero config |
| Real-time | WebSocket (ws) | Live agent status and event streaming |
| File watching | chokidar | Monitor ~/.claude/ for changes |
| Session management | tmux + child_process | Spawn and control agent processes |
| Package manager | pnpm | Fast, deterministic dependency management |
Directory Structure
/src/app/ -- Next.js pages (App Router)
layout.tsx -- Root layout
page.tsx -- Dashboard home
/teams
/new -- Team creation wizard
page.tsx
/[teamId] -- Live monitor for team
page.tsx
/audit -- Audit log
page.tsx
/templates -- Template library
page.tsx
/api
/teams -- Team CRUD endpoints
/agents -- Agent spawning/management
/tasks -- Task management
/templates -- Template import/export
/audit -- Audit log queries
/ws -- WebSocket upgrade handler
/src/components/ -- React components
/dashboard -- Home page components
/monitor -- Live monitor components
/wizard -- Team creation wizard
/templates -- Template UI
/shared -- Reusable components
/src/lib/ -- Core library code
db.ts -- SQLite connection + helpers
tmux.ts -- tmux command wrappers
watcher.ts -- ~/.claude/ file watcher
websocket.ts -- WebSocket server
types.ts -- Shared TypeScript types
/src/hooks/ -- Custom React hooks
useTeamStatus.ts -- Live team status via WebSocket
useAuditLog.ts -- Stream audit events
/db/
schema.sql -- SQLite schema
seed.sql -- Default templates
/electron/ -- Electron main process (dev build only)
main.ts -- Window and IPC management
preload.ts -- Renderer<->main bridge
tray.ts -- System tray icon/menu
updater.ts -- Auto-update logic
notifications.ts -- Native OS notifications
/data/
dashboard.db -- SQLite database (auto-created)
Database Schema
All data persists in a single SQLite database at ./data/dashboard.db.
Core tables
teams -- Agent team configurations
id(text) -- UUIDname(text) -- User-friendly nameproject_dir(text) -- Working directory pathstatus(text) -- running, paused, completed, erroredexecution_mode(text) -- tmux (v0.1) or sdk (v0.2+)created_at,ended_at(datetime) -- Timestamps
agents -- Team members
id(text) -- UUIDteam_id(text) -- FK to teamsname,role(text) -- Agent identitymodel_tier(text) -- haiku, sonnet, opussystem_prompt(text) -- Custom instructionsstatus(text) -- idle, working, waiting, completed, erroredtmux_session(text) -- tmux session:pane identifierspawned_at,ended_at(datetime)
tasks -- Work items
id(text) -- UUIDteam_id(text) -- FK to teamstitle,description(text) -- Task contentassigned_agent_id(text) -- FK to agents (nullable)created_by_agent_id(text) -- FK to agents (nullable)parent_task_id(text) -- FK to tasks (nullable, for hierarchies)status(text) -- pending, claimed, in_progress, review, completed, blockedcreated_at,completed_at(datetime)
governance_rules -- Permission boundaries
id(text) -- UUIDteam_id(text) -- FK to teamsrule_type(text) -- can_create_files, can_run_commands, can_push_git, max_turnsrule_value(text) -- 'true'/'false' or numeric string
audit_events -- Complete activity history
id(integer) -- Auto-incrementteam_id(text) -- FK to teamsagent_id(text) -- FK to agents (nullable)event_type(text) -- agent_spawned, task_created, error, etc.event_data(text) -- JSON blob with event-specific detailscreated_at(datetime)
templates -- Reusable team configs
id(text) -- UUIDname(text) -- Template namedescription(text) -- What the template doesconfig(text) -- JSON: { agents: [...], governance: {...}, prompts: {...} }created_at,updated_at(datetime)
token_usage -- LLM token tracking
id(integer) -- Auto-incrementteam_id,agent_id(text) -- FK referencesinput_tokens,output_tokens(integer)cache_read_tokens,cache_creation_tokens(integer)cost_usd(real) -- Estimated costmodel(text) -- Model used (haiku, sonnet, opus)duration_ms(integer) -- Response timesession_id(text) -- Agent session IDrecorded_at(datetime)
tool_usage -- Tool invocation tracking
id(integer) -- Auto-incrementteam_id,agent_id(text) -- FK referencestool_name(text) -- Tool invokedtool_input_summary(text) -- First 200 chars of tool inputis_mcp_tool(integer) -- Boolean: 0=built-in, 1=MCPmcp_server_name(text) -- MCP server name (if applicable)recorded_at(datetime)
schedules -- Recurring tasks
id(text) -- UUIDteam_id,agent_id(text) -- FK referencesname(text) -- Schedule nameschedule_type(text) -- 'interval' or 'cron'schedule_value(text) -- ms for interval, cron expression for cronmessage(text) -- Task message to sendenabled(integer) -- Boolean: 1=on, 0=offlast_run_at(datetime) -- When it last ranrun_count(integer) -- Total executionscreated_at(datetime)
mcp_servers -- MCP server registry
id(integer) -- Auto-incrementteam_id,agent_id(text) -- FK references (nullable)server_name(text) -- MCP server namestatus(text) -- Server statussource(text) -- 'agent-stream', 'project-config', or 'global-config'discovered_at(datetime)
Backend API Routes
All API routes are in /src/app/api/.
Team management
POST /api/teams-- Create new teamGET /api/teams-- List all teamsGET /api/teams/[teamId]-- Get team detailsPATCH /api/teams/[teamId]-- Update teamPOST /api/teams/[teamId]/end-- Graceful shutdownPOST /api/teams/[teamId]/kill-- Force termination
Agent management
POST /api/teams/[teamId]/agents-- Spawn new agentGET /api/teams/[teamId]/agents-- List team agentsPOST /api/agents/[agentId]/message-- Send message to agentPOST /api/agents/[agentId]/interrupt-- Send Ctrl+C
Task management
GET /api/teams/[teamId]/tasks-- List tasksPOST /api/teams/[teamId]/tasks-- Create taskPATCH /api/tasks/[taskId]-- Update task status
Audit log
GET /api/teams/[teamId]/audit-- Stream audit events
Templates
GET /api/templates-- List templatesPOST /api/templates-- Save templatePOST /api/templates/[templateId]/export-- Export as JSONPOST /api/templates/import-- Import from JSON
WebSocket
GET /api/ws-- Upgrade to WebSocket for live updates
Electron Packaging
The Electron layer wraps the built Next.js app. Build process:
- Compile Next.js with
pnpm build(output: standalone) - Compile Electron TypeScript files with tsc
- Package using
electron-builderwith NSIS installer - Create portable zip as an alternative distribution
The Next.js app starts as a child process in the Electron main process. The renderer connects to http://localhost:{port} where the Next.js server runs.
Real-time Updates (WebSocket)
The dashboard uses WebSocket for live agent status and event streaming.
Connection flow:
- Client opens WebSocket connection to
/api/ws - Server upgrades HTTP to WebSocket
- Client subscribes to team events:
{ action: "subscribe", teamId: "..." } - Server sends events as JSON:
{ type: "agent_status_changed", data: {...} } - Client updates UI without page reload
Supported events:
agent_status_changed-- Agent status updatetask_created/task_updated-- Task changesaudit_event-- New audit log entryagent_output-- Terminal output line
This enables live monitoring without polling.
File Watching
The watcher (lib/watcher.ts) uses chokidar to monitor ~/.claude/:
~/.claude/teams/{teamName}/config.json-- Team membership~/.claude/tasks/{teamName}/*.pending-- New tasks~/.claude/tasks/{teamName}/*.lock-- Task claims~/.claude/messages/{teamName}/*.json-- Agent messages
On file changes, the watcher parses the JSON and emits events. These feed the audit log and real-time dashboard updates.
Error Handling
All critical operations wrap in try/catch:
- Database queries: Return error in response body
- tmux commands: Retry with exponential backoff if transient
- File I/O: Log to console.error, notify user via UI
- WebSocket: Graceful disconnect and auto-reconnect on client
Silent failures are never acceptable. Users always see meaningful error messages.