RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/CLAUDE.md/23blocks-OS/ai-maestro

CLAUDE.md

CLAUDE.md
CLAUDE.mdroot

Quality

81/100

Scores the file, not the repository.

Length

5,163 words

72 headings · 39 code blocks

Repository

738

— · pushed 0 days ago

Last changed

3 days ago

First indexed 3 days ago.
23blocks-OS/ai-maestro/CLAUDE.mdRawGitHub
1# CLAUDE.md
2 
3This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4 
5## Project Overview
6 
7**Claude Code Dashboard** - A browser-based terminal dashboard for managing multiple Claude Code agents running in tmux on macOS. The application auto-discovers agents from tmux sessions and provides a unified web interface with real-time terminal streaming.
8 
9**Current Phase:** Phase 1 - Local-only, auto-discovery, no authentication
10**Tech Stack:** Next.js 14 (App Router), React 18, xterm.js, WebSocket, node-pty, Tailwind CSS, lucide-react
11**Platform:** macOS 12.0+, Node.js 18.17+/20.x, tmux 3.0+
12**Branding:** Space Grotesk font, titled "AI Maestro"
13**Port:** Application runs on port 23000 (http://localhost:23000)
14 
15## Development Commands
16 
17```bash
18# Development
19yarn install # Install all dependencies
20yarn dev # Start dev server with hot reload (http://localhost:23000)
21 
22# Production
23yarn build # Build optimized production bundle
24yarn start # Start production server (http://localhost:23000)
25pm2 restart ai-maestro # Restart production server via PM2
26 
27# Testing
28yarn test # Run unit tests (vitest)
29yarn test:watch # Run tests in watch mode
30 
31# Testing tmux sessions (for development)
32tmux new-session -s test-session # Create test session
33tmux list-sessions # List all sessions (what the app discovers)
34tmux kill-session -t test-session # Clean up test session
35```
36 
37**Port Configuration:** The application is configured to run on port 23000. This is set in the PM2 configuration.
38 
39**Health Check:** Do NOT use `/api/health` to check if the site is live (it doesn't exist). Use `/api/sessions` instead - it returns the list of agents and confirms the server is running.
40 
41## Version Management
42 
43**IMPORTANT:** When bumping the version, ALWAYS use the centralized script:
44 
45```bash
46./scripts/bump-version.sh patch # 0.17.12 -> 0.17.13
47./scripts/bump-version.sh minor # 0.17.12 -> 0.18.0
48./scripts/bump-version.sh major # 0.17.12 -> 1.0.0
49./scripts/bump-version.sh 1.0.0 # Set specific version
50```
51 
52This script updates ALL version references across the codebase:
53- `version.json` (source of truth)
54- `package.json`
55- `scripts/remote-install.sh`
56- `README.md` (badge)
57- `docs/index.html` (schema + display)
58- `docs/ai-index.html`
59- `docs/BACKLOG.md`
60 
61**DO NOT manually edit version numbers in individual files.** Always use the script to ensure consistency.
62 
63**CLI Script Versioning:** The `aimaestro-agent.sh` CLI tool uses an independent semver (`v1.x.x`) separate from the app version (`0.24.x`). The CLI is distributed via the plugin repo and has its own release cadence.
64 
65## Pre-PR Checklist (MANDATORY)
66 
67**⚠️ STOP! Before creating ANY Pull Request to main, complete this checklist:**
68 
69```
70□ 1. TESTS PASS: yarn test
71□ 2. BUMP VERSION: ./scripts/bump-version.sh patch
72□ 3. BUILD PASSES: yarn build
73□ 4. COMMIT version bump with your changes
74```
75 
76**This is NON-NEGOTIABLE.** Every PR to main MUST include a version bump. No exceptions.
77 
78---
79 
80## Release & Marketing Workflow
81 
82### Pull Request Protocol
83 
84**IMPORTANT:** Every time you create a Pull Request to main, also draft an X (Twitter) post to announce the release.
85 
86**PR Creation Checklist:**
871. ✅ **VERSION BUMPED** (see Pre-PR Checklist above - this should already be done)
882. Create PR with comprehensive description (summary, features, bug fixes, breaking changes)
893. Draft X post highlighting key features and improvements
904. Include release notes or link to PR in the post
915. Use relevant hashtags: #AIcoding #DevTools #OpenSource
926. Consider adding screenshots/GIFs for visual features
937. Post during peak hours (9-11am or 1-3pm EST)
94 
95**X Post Template:**
96```
97[Emoji] Shipping [Feature Name] today!
98 
99Key improvements:
100• [Feature 1]
101• [Feature 2]
102• [Feature 3]
103 
104[Call to action - Star/Try/Share]
105[Link to PR or GitHub]
106 
107#AIcoding #DevTools
108```
109 
110**Examples:**
111- Major release: "Shipping AI Maestro v0.3.3! 🚀"
112- Feature addition: "New feature: SSH configuration for tmux 🔐"
113- Bug fixes: "Squashed bugs and improved stability 🐛"
114 
115Keep posts concise (<280 chars when possible), engaging, and focused on user benefits rather than technical implementation.
116 
117### Marketing Content Location
118 
119**IMPORTANT:** All marketing content files MUST be created in the `marketing/` folder:
120 
121```
122marketing/
123 medium-article.md # Blog posts for Medium
124 linkedin-post.md # LinkedIn content
125 x-post.md # X/Twitter posts
126 findings.md # Research notes (planning skill)
127 task_plan.md # Task tracking (planning skill)
128 progress.md # Progress logs (planning skill)
129```
130 
131- The `marketing/` folder is gitignored - content is deleted after publishing
132- Never create these files in the project root
133- When using the planning skill for marketing tasks, set the output directory to `marketing/`
134 
135## Architecture: Critical Design Patterns
136 
137### 1. Custom Server Architecture (server.mjs)
138 
139**Why it exists:** Next.js alone doesn't support WebSocket on the same port as HTTP. The custom server combines both.
140 
141```
142HTTP Requests → Next.js handlers (API routes, pages)
143WebSocket Upgrades → Custom WS server (terminal streaming)
144Both on port 3000
145```
146 
147**Key constraint:** The server must handle:
148- HTTP/HTTPS for Next.js (pages, API routes)
149- WebSocket upgrade requests for `/term?name=<sessionName>`
150- Session discovery via `tmux ls` command execution
151 
152When modifying `server.mjs`:
153- Preserve the upgrade handler that intercepts WebSocket requests
154- Maintain the session pooling logic (multiple clients → one PTY)
155- Never block the event loop during PTY operations
156 
157### 2. Agent-First Architecture (CRITICAL)
158 
159**AGENTS ARE THE CORE ENTITY.** Sessions are optional properties of agents.
160 
161```
162Agent (core entity)
163├── id (UUID)
164├── name (agent identity, used as session name)
165├── label (optional display override)
166├── workingDirectory (stored property, NOT derived from tmux)
167├── sessions[] (array of AgentSession, typically 0 or 1)
168│ ├── index (0 for primary session)
169│ ├── status ('online' | 'offline')
170│ └── workingDirectory (optional override)
171└── preferences.defaultWorkingDirectory
172```
173 
174**Key principles:**
1751. **Agents can exist without sessions** - An agent for querying repos/documents doesn't need a tmux session
1762. **workingDirectory is STORED on the agent** - Set when agent is created or session is linked
1773. **NEVER query tmux to derive agent properties** - All agent data comes from the registry
1784. **Sessions are discovered and LINKED to existing agents** - Not the other way around
179 
180**Two agent systems:**
181- **`lib/agent-registry.ts`** - File-based registry (`~/.aimaestro/agents/registry.json`) with full agent metadata
182- **`lib/agent.ts`** - In-memory Agent class for runtime (database, subconscious)
183 
184When you need agent metadata (workingDirectory, etc.), use the file-based registry:
185```typescript
186import { getAgent, getAgentBySession } from '@/lib/agent-registry'
187const agent = getAgent(agentId) || getAgentBySession(sessionName)
188const workingDir = agent?.workingDirectory || agent?.sessions?.[0]?.workingDirectory
189```
190 
191**DO NOT:**
192- Query tmux to get working directories
193- Derive agent properties from tmux session state
194- Assume an agent always has a session
195- Create runtime lookups for data that should be stored
196 
197**Subconscious runs LOCAL to the agent:**
198 
199The subconscious process runs on the **same machine where the agent lives**. This means it has direct access to:
200- Local conversation files (`~/.claude/projects/`)
201- The agent's CozoDB database (`~/.aimaestro/agents/<id>/`)
202- The local file system (workingDirectory, repos, etc.)
203 
204The subconscious does NOT need remote API calls to access agent data - everything is local. This is why `index-delta` can read `.jsonl` files directly from disk.
205 
206**Subconscious timers (v0.18.10+):**
207- `maintainMemory()` - Indexes conversations for semantic search (runs periodically)
208- `triggerConsolidation()` - Long-term memory consolidation (runs periodically)
209- `checkMessages()` - **DISABLED by default** (push notifications replace polling)
210 
211Message polling was removed in favor of push notifications. When messages arrive, agents receive instant tmux notifications instead of waiting for the next poll cycle. To re-enable polling (not recommended), set `messagePollingEnabled: true` in the subconscious config.
212 
213### 3. Session Discovery Pattern
214 
215Sessions are discovered from tmux and LINKED to agents:
216 
217```
218/api/sessions → Execute `tmux ls` → Parse output → Link to registry agents → Return JSON
219```
220 
221**Implementation details:**
222- Agents are ephemeral - they exist only while tmux is running
223- No persistent state between dashboard restarts
224- Agent metadata comes from tmux directly (creation time, working directory)
225- The dashboard does NOT create or manage agents (Phase 1 limitation)
226 
227When implementing agent-related features:
228- Always assume agents can disappear between API calls
229- Never cache agent data longer than 5-10 seconds
230- Handle `tmux ls` returning empty results gracefully
231- Session IDs must match tmux session names exactly (alphanumeric + hyphens/underscores only)
232 
233### 3. WebSocket-PTY Bridge
234 
235**Critical data flow:**
236```
237Browser (xterm.js)
238 ↕ WebSocket messages (text/binary)
239Server (node-pty)
240 ↕ PTY (tmux attach-session -t <name>)
241tmux session
242 ↕ Claude Code CLI
243```
244 
245**Important constraints:**
246- PTY instances are pooled: Multiple WebSocket clients can connect to the same tmux session
247- PTY is created on first client connect, destroyed when last client disconnects
248- Terminal resize events must be propagated: Browser → WebSocket → PTY → tmux
249- Input/output is binary-safe (supports ANSI escape codes, Unicode, etc.)
250 
251When working with terminal components:
252- xterm.js handles rendering only - it doesn't know about tmux
253- WebSocket is the only communication channel (no polling)
254- PTY errors (session not found, tmux crashed) must close WebSocket gracefully
255- Terminal dimensions (cols/rows) must sync on window resize
256 
257### 4. Tab-Based Multi-Terminal Architecture
258 
259**Critical architectural pattern (v0.3.0+):** All agents are mounted simultaneously as "virtual tabs" with CSS visibility toggling.
260 
261**Why this architecture:**
262- Eliminates complex agent-switching logic (was 85+ lines of race condition handling)
263- Terminals initialize once on mount, never re-initialize on agent switch
264- Instant agent switching (no unmount/remount cycle)
265- Preserves terminal state, scrollback, and WebSocket connections
266- Agent notes stay in memory (no localStorage reload on switch)
267 
268**Implementation:**
269```tsx
270// app/page.tsx - All sessions rendered, toggle visibility
271{sessions.map(session => {
272 const isActive = session.id === activeSessionId
273 return (
274 <div
275 key={session.id}
276 className="absolute inset-0 flex flex-col"
277 style={{
278 visibility: isActive ? 'visible' : 'hidden',
279 pointerEvents: isActive ? 'auto' : 'none',
280 zIndex: isActive ? 10 : 0
281 }}
282 >
283 <TerminalView session={session} />
284 </div>
285 )
286})}
287```
288 
289**Why visibility:hidden instead of display:none:**
290- `display: none` removes element from layout → getBoundingClientRect() returns 0 dimensions → terminal initializes with incorrect width
291- `visibility: hidden` keeps element in layout → correct dimensions → proper terminal sizing
292- `pointerEvents: none` prevents hidden tabs from capturing mouse events
293- Text selection works immediately without agent switching
294 
295**Terminal initialization pattern:**
296```typescript
297// components/TerminalView.tsx
298useEffect(() => {
299 // Initialize ONCE on mount, never cleanup until unmount
300 const init = async () => {
301 cleanup = await initializeTerminal(containerElement)
302 setIsReady(true)
303 }
304 init()
305 
306 return () => {
307 if (cleanup) cleanup()
308 }
309}, []) // Empty deps = mount once, no session.id dependency
310```
311 
312**What was removed:**
313- Agent change detection (currentSessionRef, sessionChanged checks)
314- Race condition handling (initializingRef, duplicate initialization prevention)
315- Stale initialization cleanup verification
316- Notes/logging re-sync on agent change (loaded once on mount)
317 
318### 5. React State Management Pattern
319 
320**Deliberately minimal:** No Redux, Zustand, or complex state libraries.
321 
322```
323App State:
324- Active agent ID (localStorage persistence, drives visibility toggle)
325- Agent list (fetched from /api/sessions every 10s)
326- WebSocket connection state (per agent, persistent)
327 
328Component State:
329- Terminal instance (xterm.js, created once per agent)
330- Connection errors (transient, cleared on retry)
331- Agent notes (loaded once, persist in component state)
332```
333 
334**Key hooks:**
335- `useSessions()` - Fetches session list, auto-refreshes
336- `useTerminal()` - Manages xterm.js lifecycle (init once, resize, dispose)
337- `useWebSocket()` - Handles WebSocket connection, reconnection, message routing
338- `useActiveSession()` - Tracks selected agent with localStorage
339 
340When adding new state:
341- Keep it in the nearest component that needs it
342- Use Context only if 3+ components need the same state
343- Never store terminal content in React state (xterm.js manages this)
344- Consider if state needs to persist across agent switches (keep in component) vs. reload (use effect with session.id dependency)
345 
346### 6. UI Enhancement Patterns
347 
348**Hierarchical Agent Organization:**
349 
350Agents are organized in a 3-level hierarchy based on their names:
351```
352fluidmind/agents/backend-architect → Level 1: "fluidmind"
353 Level 2: "agents"
354 Agent: "backend-architect"
355```
356 
357**Dynamic Color System:**
358- Colors assigned via hash function (same category = same color)
359- 8-color palette in `SessionList.tsx` (easily customizable)
360- Supports localStorage overrides per category
361- No hardcoded category names - works with ANY category
362 
363```typescript
364const getCategoryColor = (category: string) => {
365 // Hash-based color assignment from COLOR_PALETTE
366 const hash = category.split('').reduce((acc, char) =>
367 char.charCodeAt(0) + ((acc << 5) - acc), 0)
368 const colorIndex = Math.abs(hash) % COLOR_PALETTE.length
369 return COLOR_PALETTE[colorIndex]
370}
371```
372 
373**Icon System:**
374- Uses lucide-react for consistent, accessible icons
375- Default icon: `Layers` (can be customized per category)
376- Icons for: folders, terminals, actions (edit, delete, create)
377 
378**Agent Notes Feature:**
379- Collapsible textarea below terminal for per-agent notes
380- Auto-saves to localStorage (`session-notes-${sessionId}`)
381- Collapse state persisted (`session-notes-collapsed-${sessionId}`)
382- Full copy/paste/edit support
383 
384**Agent Management:**
385- Rename agents with validation (API call to backend)
386- Delete agents with confirmation modal
387- Create new agents with optional working directory
388- All actions update UI optimistically with error handling
389 
390**UI Best Practices:**
391- Avoid nested buttons (causes React hydration errors)
392- Use `<div>` with `cursor-pointer` for clickable containers
393- Always use `e.stopPropagation()` for nested interactive elements
394- Keep hover states smooth with `transition-all duration-200`
395 
396### 7. Team Meeting Architecture (v0.20.19+)
397 
398**State machine pattern:** Team meetings use a `useReducer` with a `TeamMeetingState` that tracks meeting phase (`idle` → `selecting` → `ringing` → `active`), selected agents, and UI state (sidebar mode, right panel, kanban open).
399 
400**Task system:**
401- Tasks stored per-team in `~/.aimaestro/teams/tasks-{teamId}.json`
402- 5 statuses: `backlog` → `pending` → `in_progress` → `review` → `completed`
403- Dependency chains: tasks can block other tasks, auto-unblock on completion
404- `useTasks` hook polls every 5s for multi-tab sync
405 
406**Kanban board:**
407- Full-screen overlay (`fixed inset-0 z-40`) matching agent picker overlay pattern
408- Native HTML5 drag-and-drop (same pattern as AgentList.tsx)
409- `KanbanCard`: `draggable={!task.isBlocked}`, stores taskId in `dataTransfer`
410- `KanbanColumn`: `onDragOver`/`onDrop` handlers update task status
411- Escape key closes modals in priority order: detail view → quick-add → board
412- Blocked tasks show lock icon, not draggable
413 
414### 8. TypeScript Type System Organization
415 
416**Strict separation by domain:**
417 
418```
419types/session.ts - Session metadata, status enums
420types/terminal.ts - xterm.js configuration, dimensions
421types/websocket.ts - Message protocol, connection states
422```
423 
424**WebSocket message protocol:**
425```typescript
426{ type: 'input', data: string } // User typed in terminal
427{ type: 'output', data: string } // Terminal output from tmux
428{ type: 'resize', cols: number, rows: number } // Terminal resized
429{ type: 'ping' / 'pong' } // Heartbeat
430{ type: 'error', error: string } // Protocol error
431```
432 
433All WebSocket messages are JSON. Raw terminal output (ANSI codes) is wrapped in `{ type: 'output', data: ... }`.
434 
435## File Structure Conventions
436 
437**DO NOT create these directories** (they don't exist yet in Phase 1):
438- `tests/` - No test suite in Phase 1
439- `server/` - Server logic lives in root `server.mjs`
440- `public/` - No static assets currently needed
441- `styles/` - Styles in `app/globals.css` + Tailwind only
442 
443**Current structure:**
444```
445app/
446 page.tsx - Main dashboard with footer (SessionList + TerminalView)
447 layout.tsx - Root layout, Space Grotesk font, app title "AI Maestro"
448 globals.css - Tailwind imports + terminal scrollbar styles
449 api/sessions/route.ts - GET endpoint for tmux session discovery
450 
451components/
452 SessionList.tsx - Hierarchical sidebar with icons, colors, session management
453 TerminalView.tsx - Terminal display with collapsible notes area
454 [Other components] - Keep them small, single responsibility
455 team-meeting/
456 MeetingHeader.tsx - Meeting header with status, controls, kanban toggle
457 MeetingSidebar.tsx - Agent list sidebar during meetings
458 MeetingTerminalArea.tsx - Terminal grid for active meeting agents
459 MeetingRightPanel.tsx - Right panel wrapper (tasks + chat tabs)
460 MeetingChatPanel.tsx - Meeting chat using AMP messages
461 TaskPanel.tsx - Task list panel with filtering and quick-add
462 TaskCard.tsx - Task card with status, assignee, dependencies
463 TaskCreateForm.tsx - Full task creation form with all fields
464 TaskDetailView.tsx - Detailed task view with edit capabilities
465 TaskKanbanBoard.tsx - Full-screen kanban overlay with 5 columns + drag-and-drop
466 KanbanColumn.tsx - Single kanban column with drop zone
467 KanbanCard.tsx - Compact draggable task card for kanban
468 DependencyPicker.tsx - Dependency selection for task relationships
469 
470hooks/
471 useWebSocket.ts - WebSocket connection (reconnection, heartbeat)
472 useTerminal.ts - xterm.js lifecycle (init, fit, dispose)
473 useSessions.ts - Session list fetching + auto-refresh
474 useTasks.ts - Task CRUD with tasksByStatus, optimistic updates, 5s polling
475 useMeetingMessages.ts - Meeting chat messages via AMP with 7s polling
476 
477lib/
478 api.ts - Fetch wrappers for /api/sessions
479 websocket.ts - WebSocket message creators
480 terminal.ts - Terminal utility functions
481 utils.ts - Shared utilities (date formatting, etc.)
482 
483types/
484 session.ts - Session metadata, status enums, hierarchical structure
485 terminal.ts - xterm.js configuration, dimensions
486 websocket.ts - Message protocol, connection states
487 
488docs/
489 images/ - Screenshots for README documentation
490 REQUIREMENTS.md - Installation prerequisites
491 OPERATIONS-GUIDE.md - Session management, troubleshooting
492 
493plugin/ - Plugin submodule (git submodule from 23blocks-OS/ai-maestro-plugins)
494 .claude-plugin/ - Marketplace manifest
495 plugins/ai-maestro/ - The AI Maestro plugin
496 scripts/ - All CLI scripts (AMP, graph, docs, memory, agent management)
497 skills/ - All 6 Claude Code skills
498 hooks/ - Session tracking hooks
499 .claude-plugin/ - Plugin manifest
500 
501scripts/
502 generate-social-logos.js - Generate social media logos from SVG
503 init-all-agents.mjs - Initialize memory for all agents
504 register-agent-from-session.mjs - Register agent(s) from tmux session(s)
505 setup-tmux.sh - Setup tmux configuration
506 
507install-plugin.sh - Plugin installer (skills, scripts, CLI tools)
508 
509server.mjs - Custom Next.js server (HTTP + WebSocket)
510CLAUDE.md - This file - guidance for Claude Code
511```
512 
513## Agent Messaging Protocol (AMP)
514 
515**Overview:** AI Maestro uses the Agent Messaging Protocol (AMP) for inter-agent communication. AMP is like email for AI agents - it works locally by default and can optionally federate with external providers.
516 
517**Key Features:**
518- **Local-first**: Works immediately without external dependencies
519- **Cryptographic signing**: Ed25519 signatures for message authenticity
520- **Federation**: Connect to external providers (CrabMail, etc.) for global messaging
521- **Provider-agnostic**: Same CLI works with any AMP provider
522 
523### Installation
524 
525The AMP plugin is bundled in the plugin submodule at `plugin/plugins/ai-maestro/`.
526 
527```bash
528# Install AMP scripts and skills
529./install-plugin.sh
530 
531# Non-interactive installation
532./install-plugin.sh -y
533 
534# Migrate existing messages only
535./install-plugin.sh --migrate
536```
537 
538**What gets installed:**
539- AMP scripts (`amp-*.sh`) → `~/.local/bin/`
540- AMP skill → `~/.claude/skills/agent-messaging/`
541- Message storage → `~/.agent-messaging/`
542 
543### Quick Start
544 
545```bash
546# 1. Initialize your agent identity (first time only)
547amp-init.sh --auto
548 
549# 2. Send a message
550amp-send.sh alice &quot;Hello&quot; &quot;How are you?&quot;
551 
552# 3. Check your inbox
553amp-inbox.sh
554 
555# 4. Read a message
556amp-read.sh &lt;message-id&gt;
557```
558 
559### Architecture
560 
561**Two Components:**
562 
5631. **AMP Plugin (Client)** - Installed on each agent machine
564 - Location: `plugin/plugins/ai-maestro/` (submodule)
565 - Storage: `~/.agent-messaging/`
566 - Commands: `amp-init`, `amp-send`, `amp-inbox`, `amp-read`, etc.
567 - Handles: Key generation, message signing, local storage
568 
5692. **AI Maestro (Provider)** - Server that routes messages
570 - Endpoints: `/api/v1/register`, `/api/v1/route`, `/api/v1/messages/pending`
571 - Handles: Message routing, relay queue, push notifications
572 - Optional: Agents can use external providers (CrabMail) instead
573 
574**Message Storage (Client-side):**
575```
576~/.agent-messaging/
577├── config.json # Agent configuration
578├── keys/
579│ ├── private.pem # Ed25519 private key (never shared)
580│ └── public.pem # Ed25519 public key
581├── messages/
582│ ├── inbox/ # Received messages
583│ └── sent/ # Sent messages
584└── registrations/ # External provider registrations
585```
586 
587### AMP CLI Commands
588 
589| Command | Description |
590|---------|-------------|
591| `amp-init.sh --auto` | Initialize agent identity |
592| `amp-status.sh` | Show agent status and registrations |
593| `amp-inbox.sh` | Check inbox for messages |
594| `amp-read.sh <id>` | Read a specific message |
595| `amp-send.sh <to> <subject> <message>` | Send a message |
596| `amp-reply.sh <id> <message>` | Reply to a message |
597| `amp-delete.sh <id>` | Delete a message |
598| `amp-register.sh --provider <url>` | Register with external provider |
599| `amp-fetch.sh` | Fetch messages from external providers |
600 
601### Address Formats
602 
603**Local addresses** (work immediately):
604- `alice` → `alice@default.local`
605- `bob@myteam.local` → Local delivery
606 
607**External addresses** (require registration):
608- `alice@acme.crabmail.ai` → Via CrabMail provider
609- `backend@company.otherprovider.com` → Via other provider
610 
611### Provider API (v0.20.0+)
612 
613AI Maestro can act as an AMP provider. Agents register with AI Maestro and it handles routing.
614 
615**Endpoints:**
616- `GET /api/v1/health` - Provider health status (no auth)
617- `GET /api/v1/info` - Provider capabilities (no auth)
618- `POST /api/v1/register` - Register agent, get API key
619- `POST /api/v1/route` - Route a signed message
620- `GET /api/v1/messages/pending` - Poll for offline messages
621- `DELETE /api/v1/messages/pending?id=X` - Acknowledge message
622 
623**Registration flow:**
624```bash
625# Agent registers with local AI Maestro
626amp-register.sh --provider localhost:23000 --tenant myorg
627# Returns API key, stores in ~/.agent-messaging/registrations/
628```
629 
630### Push Notifications
631 
632When a message is routed to a local agent, AI Maestro sends a push notification via tmux:
633 
634```
635[MESSAGE] From: alice - Subject line - check your inbox
636```
637 
638**Configuration (environment variables):**
639- `NOTIFICATIONS_ENABLED=false` - Disable push notifications
640- `NOTIFICATION_FORMAT` - Customize notification format
641 
642### Message Storage
643 
644All messages are stored in AMP per-agent directories:
645```
646~/.agent-messaging/agents/<agentName>/messages/inbox/
647~/.agent-messaging/agents/<agentName>/messages/sent/
648```
649 
650Per-agent directories are auto-created when agents first use AMP commands.
651The old `~/.aimaestro/messages/` system is no longer used.
652 
653### Claude Code Skill
654 
655The AMP skill (`plugin/plugins/ai-maestro/skills/agent-messaging/SKILL.md`) provides natural language:
656 
657```
658"Check my messages" → amp-inbox.sh
659"Send a message to backend-api about deployment" → amp-send.sh backend-api "Deployment" "..."
660"Reply to the last message" → amp-reply.sh <id> "..."
661```
662 
663### Development Notes
664 
665- **Submodule**: Plugin repo is at `plugin/` - update with `git submodule update --remote`
666- **Protocol spec**: https://agentmessaging.org
667- **Security**: Messages are signed with Ed25519; AI Maestro verifies signatures
668- **Relay queue**: Offline agents get messages via polling (`/api/v1/messages/pending`)
669 
670## Critical Implementation Details
671 
672### Terminal Rendering Performance
673 
674xterm.js uses **Canvas or WebGL** for rendering. The WebGL addon significantly improves performance for high-output scenarios (e.g., large file dumps).
675 
676```typescript
677// In useTerminal hook
678try {
679 const webglAddon = new WebglAddon()
680 terminal.loadAddon(webglAddon)
681} catch (e) {
682 // Fallback to canvas if WebGL unavailable
683}
684```
685 
686**Never** read terminal content via React state. Always use xterm.js APIs (`terminal.write()`, `terminal.onData()`).
687 
688### Critical Terminal Configuration for PTY/tmux
689 
690**IMPORTANT:** The following terminal settings are critical for proper Claude Code CLI behavior:
691 
6921. **`convertEol: false`** - PTY and tmux handle line endings correctly. Setting this to `true` causes character duplication and incorrect line breaks because xterm.js will convert `\n` to `\r\n`, but the PTY has already handled this.
693 
6942. **Alternate Screen Buffer Support** - Claude Code (like vim, less, etc.) uses tmux's alternate screen buffer. This means:
695 - When Claude is active, it uses a separate screen that doesn't mix with your shell history
696 - Scrollback must be captured from tmux's buffer, not just xterm.js's buffer
697 - The `windowOptions: { setWinLines: true }` setting enables proper alternate buffer support
698 
6993. **Scrollback Capture Strategy** - On initial connection, capture both normal and alternate screen content:
700```bash
701 # Try to capture full history (50000 lines)
702 tmux capture-pane -t &lt;session&gt; -p -S -50000 -e -1
703 # Fallback to visible content only
704 tmux capture-pane -t &lt;session&gt; -p
705```
706 
707**Common Issues and Fixes:**
708 
709- **Every character creates a new line**: `convertEol` was set to `true` - must be `false` for PTY connections
710- **Can't scroll back during Claude session**: Claude Code uses alternate screen buffer - use Shift+PageUp/Down to scroll xterm.js buffer, or tmux copy mode (Ctrl-b [) to access tmux's scrollback
711- **Lost history after switching agents**: History capture timeout was too short or tmux session not fully initialized - increased timeout to 150ms
712 
713### WebSocket Reconnection Strategy
714 
715```typescript
716const reconnect = {
717 maxAttempts: 5,
718 backoff: [100, 500, 1000, 2000, 5000], // Exponential backoff
719 strategy: 'exponential'
720}
721```
722 
723After 5 failed reconnection attempts, show error to user. Do NOT retry indefinitely (would waste resources if tmux session truly ended).
724 
725### Session Naming Constraints
726 
727tmux session names are limited to: `^[a-zA-Z0-9_-]+$`
728 
729**Enforce this** in any UI that creates sessions (Phase 2+). Invalid characters will cause `tmux attach` to fail silently.
730 
731### Localhost-Only Security Model
732 
733**Phase 1 security assumptions:**
734- Application binds to `localhost` (127.0.0.1) ONLY
735- No authentication required (OS-level user security)
736- No CORS, no origin validation
737- WebSocket connections accepted from any localhost origin
738 
739**DO NOT implement:**
740- User authentication (not needed for localhost)
741- Agent-level permissions (all agents accessible to local user)
742- HTTPS/TLS (overkill for localhost)
743 
744These are deferred to Phase 2+ if remote access is needed.
745 
746## Common Gotchas
747 
748### 1. Terminal Not Fitting Container
749 
750```typescript
751// After terminal.open(container), ALWAYS call:
752fitAddon.fit()
753 
754// And on window resize:
755window.addEventListener('resize', () => fitAddon.fit())
756```
757 
758Without this, terminal dimensions won't match the container, causing ugly scrollbars.
759 
760### 2. Hidden Terminals Must Use visibility:hidden, NOT display:none
761 
762**CRITICAL (v0.3.0+):** When hiding inactive terminal tabs, use `visibility: hidden` instead of `display: none`.
763 
764```tsx
765// ✅ CORRECT - Keeps element in layout
766style={{
767 visibility: isActive ? 'visible' : 'hidden',
768 pointerEvents: isActive ? 'auto' : 'none',
769 zIndex: isActive ? 10 : 0
770}}
771 
772// ❌ WRONG - Removes from layout
773style={{
774 display: isActive ? 'flex' : 'none'
775}}
776```
777 
778**Why this matters:**
779- `display: none` removes element from layout → `getBoundingClientRect()` returns width/height = 0
780- Terminal initializes with 0 dimensions → gets minimum columns (2) instead of full width
781- Hidden elements don't receive mouse events → selection/copy doesn't work
782- Using `visibility: hidden` + `pointerEvents: none` keeps correct dimensions while preventing interaction
783 
784### 3. WebSocket Lifecycle vs React Lifecycle
785 
786```typescript
787useEffect(() => {
788 const ws = new WebSocket(url)
789 // ... setup handlers ...
790 
791 return () => {
792 ws.close() // CRITICAL: Clean up on unmount
793 }
794}, []) // Empty deps with tab architecture - WebSocket persists across visibility changes
795```
796 
797**Tab-based architecture change (v0.3.0+):** WebSocket connections are no longer recreated on agent switch. They're created once on mount and persist until component unmounts (when agent is removed from the list).
798 
799### 4. tmux Session Name Parsing
800 
801`tmux list-sessions` output format:
802```
803session-name: 1 windows (created Tue Jan 10 14:23:45 2025)
804```
805 
806Parsing must handle:
807- Session names with hyphens/underscores
808- Timestamps in various formats (locale-dependent)
809- Multiple windows (number can be > 9)
810 
811Use robust regex: `/^([a-zA-Z0-9_-]+):/`
812 
813### 5. xterm.js Addon Loading Order
814 
815```typescript
816terminal.loadAddon(fitAddon) // 1. Load addons first
817terminal.loadAddon(webLinksAddon)
818terminal.open(container) // 2. Then open
819fitAddon.fit() // 3. Then fit
820```
821 
822Wrong order causes crashes or non-functional addons.
823 
824## Environment Variables
825 
826All optional, with sensible defaults:
827 
828```bash
829PORT=3000 # Server port
830NODE_ENV=development|production # Next.js environment
831WS_RECONNECT_DELAY=3000 # WebSocket reconnect delay (ms)
832WS_MAX_RECONNECT_ATTEMPTS=5 # Max reconnection attempts
833TERMINAL_FONT_SIZE=14 # xterm.js font size
834TERMINAL_SCROLLBACK=10000 # Terminal scrollback buffer
835```
836 
837Set via `.env.local` (gitignored). Never commit `.env.local`.
838 
839## Server Modes
840 
841AI Maestro supports two server modes controlled by the `MAESTRO_MODE` environment variable:
842 
843### Full Mode (default)
844```bash
845yarn dev # Development with hot reload
846yarn start # Production
847```
848- Uses Next.js for both UI pages and API routes
849- All features available: dashboard, terminal WebSockets, API endpoints
850- Startup: ~5s, Memory: ~300MB
851 
852### Headless Mode
853```bash
854yarn headless # Development
855yarn headless:prod # Production
856```
857- API-only mode — no Next.js, no UI pages
858- All ~100 API endpoints served via standalone HTTP router (`services/headless-router.ts`)
859- WebSocket connections (terminal, AMP, status, companion) work identically
860- Uses `tsx` for TypeScript support (resolves `@/*` paths via tsconfig.json)
861- Startup: ~1s, Memory: ~100MB
862- Ideal for worker nodes that only need the API surface
863 
864**Architecture:**
865- `server.mjs` branches on `MAESTRO_MODE` at startup
866- Full mode: `node server.mjs` → Next.js `app.prepare()` → `handle(req, res)`
867- Headless mode: `tsx server.mjs` → `createHeadlessRouter()` → `router.handle(req, res)`
868- All WebSocket servers, PTY handling, startup tasks, and graceful shutdown are shared between modes
869- The `/api/internal/pty-sessions` endpoint is served directly from `server.mjs` in both modes
870 
871## Testing the Application
872 
873**Manual testing workflow:**
874 
8751. Start the dashboard: `npm run dev`
8762. Create test tmux sessions:
877```bash
878 tmux new-session -s test1 -d
879 tmux send-keys -t test1 'claude' C-m
880 tmux new-session -s test2 -d
881 tmux send-keys -t test2 'claude' C-m
882```
8833. Verify auto-discovery: Sessions appear in sidebar
8844. Click sessions: Terminal content loads
8855. Type in terminal: Input reaches Claude
8866. Kill session: `tmux kill-session -t test1`
8877. Verify: Session removed after refresh
888 
889### Unit Tests (CI — runs in GitHub Actions)
890 
891Unit tests use vitest and run on every push/PR via `.github/workflows/ci.yml`:
892 
893```bash
894yarn test # Run all unit tests
895yarn test:watch # Watch mode
896```
897 
898Tests cover: agent utilities, session service, agents-core service, AMP auth/address/canonical-json, task registry, team registry, document registry, container utils, meeting inject, content security. All service tests mock the runtime layer — no tmux/network required.
899 
900### Integration Test Suites (Manual — requires running AI Maestro)
901 
902These scripts test end-to-end behavior against a live AI Maestro instance with tmux:
903 
904```bash
905# AMP local routing tests (single host)
906# Tests: health, registration, internal→internal, external polling, federation, acknowledgment
907./scripts/test-amp-routing.sh
908 
909# AMP cross-host mesh tests (multi-host via Tailscale)
910# Tests: host health, agent registration on each host, cross-host delivery, replies, inbox counts
911./scripts/test-amp-cross-host.sh # Auto-detect hosts from ~/.aimaestro/hosts.json
912./scripts/test-amp-cross-host.sh --local-only # Only test local→remote
913./scripts/test-amp-cross-host.sh --skip-inbox # Skip inbox verification
914 
915# Companion call session fork tests
916# Tests: __call session spawn, sidebar/agent hiding, transcript routing, disconnect cleanup, multi-client
917./scripts/test-call-session.sh # Auto-picks first online agent
918./scripts/test-call-session.sh &lt;agent-id&gt; # Specific agent
919```
920 
921**Prerequisites:** AI Maestro running on localhost:23000, jq installed, tmux installed. AMP tests also require AMP scripts (`./install-plugin.sh -y`).
922 
923## Documentation References
924 
925- **[README.md](./README.md)** - Project overview, quick start, architecture
926- **[docs/REQUIREMENTS.md](./docs/REQUIREMENTS.md)** - Installation prerequisites
927- **[docs/OPERATIONS-GUIDE.md](./docs/OPERATIONS-GUIDE.md)** - Agent management, troubleshooting
928- **[docs/CEREBELLUM.md](./docs/CEREBELLUM.md)** - Cerebellum subsystem architecture, voice pipeline, TTS providers
929 
930Refer to these when users ask about setup or usage.
931 
932## Roadmap Context
933 
934**Phase 1 (Current):** Auto-discovery, localhost-only, read-only agent interaction
935**Phase 2 (Planned):** Agent creation from UI, grouping, search
936**Phase 3 (Future):** Remote SSH sessions, authentication, collaboration
937 
938When implementing features:
939- Check if they belong in current phase
940- Don't over-engineer for future phases
941- Document phase boundaries clearly
942 
943## What NOT to Do
944 
945- **Don't query tmux to get agent properties** - workingDirectory, etc. are STORED on the agent in the registry, not derived from tmux. See "Agent-First Architecture" section.
946- **Don't assume agents need sessions** - Agents are the core entity; sessions are optional. An agent can exist for querying repos/docs without a tmux session.
947- **Don't use sessions.json** - Sessions are auto-discovered from tmux
948- **Don't implement authentication** - Phase 1 is localhost-only
949- **Don't store terminal history** - xterm.js manages scrollback in-memory
950- **Don't use polling** - WebSocket only for terminal I/O
951- **Don't support remote SSH** - Phase 3 feature, not Phase 1
952- **Don't nest interactive elements** - Causes React hydration errors (use div with onClick instead)
953- **Don't hardcode category colors** - Use the hash-based dynamic color system
954- **Don't use display:none for hidden terminals** - Use visibility:hidden to maintain correct dimensions and enable selection (v0.3.0+)
955- **Don't add session.id to terminal initialization useEffect** - Terminals initialize once with empty dependency array in tab architecture (v0.3.0+)
956 
957## Key Files to Understand
958 
959**Must read to understand the system:**
960 
9611. `lib/agent-registry.ts` - **File-based agent registry** (stores agents in `~/.aimaestro/agents/registry.json`) - THE source of truth for agent metadata including workingDirectory
9622. `lib/agent.ts` - **In-memory Agent class** for runtime operations (database, subconscious)
9633. `server.mjs` - Custom server combining HTTP and WebSocket
9644. `app/page.tsx` - Main UI composition with footer (SessionList + TerminalView)
9655. `components/SessionList.tsx` - Hierarchical sidebar with dynamic colors, icons, agent management
9666. `components/TerminalView.tsx` - Terminal display with collapsible notes feature
9677. `hooks/useWebSocket.ts` - WebSocket connection management
9688. `hooks/useTerminal.ts` - xterm.js lifecycle management
9699. `app/api/sessions/route.ts` - tmux session discovery logic
970 
971**Team Meeting & Kanban (v0.20.19+):**
97210. `app/team-meeting/page.tsx` - Team meeting page with reducer state machine
97311. `components/team-meeting/TaskKanbanBoard.tsx` - Full-screen kanban overlay with 5 columns + drag-and-drop
97412. `components/team-meeting/KanbanColumn.tsx` - Single kanban column with drop zone
97513. `components/team-meeting/KanbanCard.tsx` - Compact draggable task card
97614. `types/task.ts` - Task types with 5 statuses: backlog, pending, in_progress, review, completed
97715. `lib/task-registry.ts` - File-based CRUD for team task persistence
97816. `hooks/useTasks.ts` - Task hook with tasksByStatus, optimistic updates, polling
979 
980**Read these in order** to understand agents and data flow.
981 
982**Key UI patterns:**
983- Tab-based multi-terminal architecture (v0.3.0+) - all agents mounted, visibility toggling
984- Dynamic color assignment (hash-based, no hardcoding)
985- Hierarchical grouping (3-level: category/subcategory/agent)
986- Agent notes (per-agent localStorage)
987- Avoid nested buttons (use div with cursor-pointer)
988- Use visibility:hidden for inactive tabs (not display:none)
989 

Commands it names

  • yarn install
  • yarn dev
  • yarn build
  • yarn start
  • yarn test
  • yarn test:watch
  • yarn headless
  • yarn headless:prod
  • git submodule update --remote
  • node server.mjs
  • npm run dev

Sections

  • CLAUDE.md
  • Project Overview
  • Development Commands
  • Development
  • Production
  • Testing
  • Testing tmux sessions (for development)
  • Version Management
  • Pre-PR Checklist (MANDATORY)
  • Release & Marketing Workflow
  • Pull Request Protocol
  • Marketing Content Location
  • Architecture: Critical Design Patterns
  • 1. Custom Server Architecture (server.mjs)
  • 2. Agent-First Architecture (CRITICAL)
  • 3. Session Discovery Pattern
  • 3. WebSocket-PTY Bridge
  • 4. Tab-Based Multi-Terminal Architecture
  • 5. React State Management Pattern
  • 6. UI Enhancement Patterns
  • 7. Team Meeting Architecture (v0.20.19+)
  • 8. TypeScript Type System Organization
  • File Structure Conventions
  • Agent Messaging Protocol (AMP)
  • Installation
  • Install AMP scripts and skills
  • Non-interactive installation
  • Migrate existing messages only
  • Quick Start
  • 1. Initialize your agent identity (first time only)
  • 2. Send a message
  • 3. Check your inbox
  • 4. Read a message
  • Architecture
  • AMP CLI Commands
  • Address Formats
  • Provider API (v0.20.0+)
  • Agent registers with local AI Maestro
  • Returns API key, stores in ~/.agent-messaging/registrations/
  • Push Notifications
  • Message Storage
  • Claude Code Skill
  • Development Notes
  • Critical Implementation Details
  • Terminal Rendering Performance
  • Critical Terminal Configuration for PTY/tmux
  • WebSocket Reconnection Strategy
  • Session Naming Constraints
  • Localhost-Only Security Model
  • Common Gotchas
  • 1. Terminal Not Fitting Container
  • 2. Hidden Terminals Must Use visibility:hidden, NOT display:none
  • 3. WebSocket Lifecycle vs React Lifecycle
  • 4. tmux Session Name Parsing
  • 5. xterm.js Addon Loading Order
  • Environment Variables
  • Server Modes
  • Full Mode (default)
  • Headless Mode
  • Testing the Application

What it covers

setuptestcode-stylearchitecturetypestesting-strategygit-prsecurityapiuiperformancedeploymentdo-notagent-behaviour

Stack — with the evidence

typescript

(1.00)

node

(1.00)

nextjs

(1.00)

tailwind

(1.00)

vitest

(1.00)

eslint

(1.00)

react

(0.70)

postgres

(0.70)

javascript

(0.60)

terraform

(0.60)

github-actions

(0.60)

Format

CLAUDE.md

Claude Code's memory file. Shaped like AGENTS.md but with two things it lacks: @path imports, so shared rules live in one place, and a user-scope layer that follows the developer across repos rather than shipping with the code.

What the corpus says about it

Repository

Owner
23blocks-OS
Language
—
License
—
Archived
no

All configs in this repo

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
Adit-Jain-srm/NightmareNetCLAUDE.md · 45CLAUDE.mdtypescriptpython+18buildtestlint-formatstyle+6100/1003 days ago
bagisto/bagistoCLAUDE.md · 28kCLAUDE.mdphplaravel+8setupbuildteststyle+5100/1003 days ago
microsoft/playwrightCLAUDE.md · 94kCLAUDE.mdtypescriptjavascript+10buildtestlint-formatstyle+7100/1003 days ago
dotCMS/corecore-web/CLAUDE.md · 949CLAUDE.mdjavanode+13teststylearchtesting-strategy+3100/1003 days ago
nimbalyst/nimbalystpackages/android/CLAUDE.md · 1.4kCLAUDE.mdtypescriptnode+16setupbuildstylearch+2100/1003 days ago
filamentphp/filamentCLAUDE.md · 32kCLAUDE.mdphplaravel+5buildtestlint-formatstyle+7100/1003 days ago
dotCMS/coreCLAUDE.md · 949CLAUDE.mdjavanode+9setupbuildteststyle+799/100today
lollipopkit/flutter_server_boxCLAUDE.md · 8.3kCLAUDE.mddartflutter+8buildteststylearch+298/1003 days ago
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack