
Multi-agent interactive control center — monitor, control, and analyze AI agents in a shared pixel-art office. Built for Claude Code agent teams.

- Real-time monitoring — Watches Claude Code
.jsonl session files and visualizes agent activity live
- Multi-user collaboration — Multiple users share the same office with nicknames, chat, and presence indicators
- Agent control — Kill or restart agents directly from the UI; send text commands to agents
- Permission approval — Review and approve/reject agent permission requests in real time
- Session replay — Replay past sessions with a timeline (Gantt chart) and event log
- Statistics dashboard — Chart.js-powered tool usage stats per session and agent
- Pixel-art office — Canvas 2D rendered office with animated pixel characters
- Agent states — Visual feedback for spawning, working, typing, searching, reading, executing, awaiting approval, idle, and despawning
- Parent-child visualization — Sub-agents linked to their parent agents with visual connections
- Layout editor — Built-in office editor with walls, floors, furniture, and workstations; versioned saves with conflict detection
- Graceful degradation — Automatically simplifies rendering when agent count exceeds thresholds
- Performance monitoring — Real-time FPS, event rate, and agent count panel
- Notification system — Desktop-style notifications for key events
- Sound effects — Synthesized audio cues using Web Audio API (no external files)
- Structured logging — File-rotated logs (server, parser, db, error) with configurable levels
- REST API — Sessions, events, stats, and health endpoints for external integrations
- Zero Node.js — Pure Python backend + vanilla HTML/CSS/JS frontend, no build steps
pip install -r requirements.txt
python start.py
The browser opens automatically at http://localhost:8765.
Press Ctrl+C to stop.
Edit config.yaml:
server:
host: "localhost" # 0.0.0.0 for LAN access
port: 8765
websocket:
heartbeat_interval: 15 # seconds between heartbeat broadcasts
heartbeat_timeout: 45 # seconds before stale connection is removed
database:
path: "data/pixoffice.db"
wal_mode: true
max_size_mb: 500
retention_days: 30
watch:
path: "~/.claude/projects" # Claude Code session directory
timeouts:
idle_timeout: 30 # seconds before agent goes idle
session_timeout: 600 # seconds before agent despawns
performance:
max_agents_before_degraded: 20
max_agents_before_icon_mode: 50
logging:
level: "INFO"
dir: "logs"
max_file_mb: 10
backup_count: 5
| Section |
Option |
Default |
Description |
server |
host |
localhost |
Listen address. 0.0.0.0 for LAN |
server |
port |
8765 |
Server port |
websocket |
heartbeat_interval |
15 |
Seconds between heartbeat broadcasts |
websocket |
heartbeat_timeout |
45 |
Seconds before stale connection removal |
database |
path |
data/pixoffice.db |
SQLite database path |
database |
retention_days |
30 |
Data retention period |
watch |
path |
~/.claude/projects |
Directory to watch for .jsonl files |
timeouts |
idle_timeout |
30 |
Seconds before inactive agent goes idle |
timeouts |
session_timeout |
600 |
Seconds before inactive agent despawns |
performance |
max_agents_before_degraded |
20 |
Agent count for degraded mode |
performance |
max_agents_before_icon_mode |
50 |
Agent count for icon-only mode |
logging |
level |
INFO |
Log level (DEBUG/INFO/WARNING/ERROR) |
Claude Code sessions → .jsonl files → watchdog → parse events → state manager → WebSocket → browser render
↕
SQLite persistence
- File watcher —
watchdog recursively monitors .jsonl files in the configured path
- Event parser — Extracts tool usage, messages, and permission requests from JSONL lines
- State manager — Tracks agent lifecycle (spawn → work → idle → despawn) with zombie detection
- WebSocket hub — Pushes state updates to all connected browser clients; manages heartbeats, nicknames, and layout versioning
- Canvas renderer — Draws the office scene with character animations, speech bubbles, and effects
- Database — Persists sessions, events, and stats to SQLite with automatic cleanup
- REST API — Exposes session history, event timeline, and tool usage statistics
| State |
Color |
Description |
| Spawning |
Green pulse |
Agent just created |
| Working |
Green |
Active and working |
| Writing |
Blue |
Writing code (bubble shows tool name) |
| Searching |
Orange |
Searching codebase |
| Reading |
Purple |
Reading files |
| Executing |
Dark orange |
Running terminal commands |
| Awaiting approval |
Red pulse |
Waiting for user authorization |
| Idle |
Gray |
Timed out, wandering around |
| Despawning |
Red fast pulse |
Session expired, despawn effect |
| Input |
Action |
E |
Toggle edit/view mode |
R |
Rotate furniture (edit mode) |
Delete |
Delete furniture under cursor |
Ctrl+Z / Ctrl+Shift+Z |
Undo / Redo |
Ctrl+Scroll |
Zoom (1x–10x) |
Middle-click drag |
Pan canvas |
mpixoffice/
├── start.py # Entry point
├── config.yaml # Configuration
├── requirements.txt # Dependencies
├── server/
│ ├── __init__.py # Package init
│ ├── app.py # Application factory, middleware, startup hooks
│ ├── routes.py # HTTP/WebSocket routes + REST API
│ ├── ws_hub.py # WebSocket broadcast hub (heartbeat, nicknames, layout versioning)
│ ├── state.py # Agent state management (lifecycle, idle/zombie detection)
│ ├── db.py # SQLite persistence layer with migration framework
│ ├── parser.py # JSONL event parser
│ ├── watcher.py # File system watcher
│ ├── types.py # Data type definitions (Agent, AgentStatus, PermissionRequest)
│ ├── permission.py # Permission approval/rejection handling
│ ├── agent_control.py # Agent kill/restart operations
│ └── logger.py # Structured logging with file rotation
├── web/
│ ├── index.html # Main page (HTML + CSS + JS)
│ ├── css/ # Stylesheets
│ └── js/
│ ├── renderer.js # Canvas rendering engine
│ ├── camera.js # Viewport control
│ ├── character.js # Character animations (box-shadow pixel art)
│ ├── websocket.js # WebSocket client
│ ├── replay.js # Session replay manager
│ ├── timeline.js # Gantt chart timeline
│ ├── chart-panel.js # Chart.js statistics panel
│ ├── chat.js # Chat component
│ ├── permission-bubble.js # Permission approval bubbles
│ ├── identity.js # User identity / nickname system
│ ├── notification.js # Notification system
│ ├── perf-panel.js # Performance monitoring panel
│ ├── degradation.js # Graceful degradation strategy
│ ├── pathfinding.js # A* pathfinding
│ ├── sprite-data.js # Sprite definitions
│ ├── sprite-cache.js # Sprite caching
│ ├── palettes.js # Color palettes
│ ├── spawn-effect.js # Spawn/despawn effects
│ └── sound.js # Audio synthesis
├── layouts/
│ └── default.json # Default office layout (30×16 grid)
├── migrations/
│ └── 001_init.sql # Database migration
├── docs/
│ ├── screenshot.png # Project screenshot
│ └── USER_GUIDE.md # Detailed user guide (Chinese)
└── tests/ # Unit tests
├── test_parser.py
├── test_state.py
├── test_multi_agent.py
└── test_error_handling.py
| Endpoint |
Method |
Description |
/health |
GET |
System health (uptime, agents, DB status, degradation level) |
/api/sessions |
GET |
List sessions (optional ?date=YYYY-MM-DD filter) |
/api/sessions/{id} |
GET |
Session detail with agent list |
/api/events |
GET |
Events for a session (?session_id=...) |
/api/stats |
GET |
Tool usage stats (?session_id=...&agent_id=...) |
python -m pytest tests/ -v
| Layer |
Technology |
| Backend |
Python 3.10+, aiohttp, aiosqlite, watchdog, PyYAML |
| Frontend |
HTML5 Canvas 2D, vanilla JavaScript, Chart.js (CDN) |
| Communication |
WebSocket (aiohttp) |
| Database |
SQLite + aiosqlite (WAL mode) |
| Audio |
Web Audio API (synthesized) |
| Logging |
Python logging + RotatingFileHandler |
| Testing |
pytest, pytest-asyncio |
- User Guide — Detailed guide with configuration, controls, layout system, and WebSocket protocol (Chinese)
- Contributing — Development setup and contribution guidelines
MIT