🚨 READ THIS ENTIRE FILE 🚨 CRITICAL: You MUST read this complete file from start to finish. Do not truncate or skip sections.
Note: This is a revolutionary multi-workspace orchestrator for managing unlimited Claude Code sessions with mixed-repository support, dynamic worktree creation, and zero-friction workflows.
When creating any pull request, ALWAYS provide the PR URL in your response to the user. This is mandatory for all PRs.
If you ever lose context mid-run, do not improvise. Resume from these files:
PLANS/2026-01-20/REQUESTED_CHANGES.md(master list of requested fixes)PLANS/2026-01-20/ROLLING_LOG.md(what shipped; PR links; where to resume)PLANS/2026-01-24/OPTIMAL_ORCHESTRATOR_PROCESS.md(tier + queue model)PLANS/2026-01-25/WORKFLOW_TIER_RISK_PROMPTS.md(current open items: tiers, risk, prompts, review inbox)PLANS/2026-01-25/BRAIN_DUMP_2026-01-25.md(full workflow brain dump transcript)PLANS/2026-01-25/BRAIN_DUMP_IMPLEMENTATION_PLAN.md(what’s missing + next PRs)PLANS/2026-01-25/DATA_MODEL.md(where tiers/deps/prompts live)
Current open PRs (keep updated in the rolling log):
- None (check with
gh pr list --state open)
Commander/voice can drive the tiered workflow via semantic commands:
set-workflow-mode(focus|review|background)set-focus-tier2(auto|always)open-queue,open-tasks,open-advice
Tier tagging persistence:
- stored in
~/.orchestrator/task-records.jsonviasession:<id>task records - loaded on page refresh via
GET /api/process/task-records
CRITICAL: Always check ~/.claude/TRELLO_BOARDS.md for the full board/list/repo mapping. Do NOT assume a board maps to a specific repo - look it up!
| Board | Board ID | Repo Path | Repo Type |
|---|---|---|---|
| Zoo Hytopia | 691e5516c77f3e9c9fd89f61 |
~/GitHub/games/hytopia/zoo-game/ |
hytopia-game |
| Arcade World | 694a07bae349c125d4568094 |
~/GitHub/games/hytopia/games/hytopia-2d-game-test/ |
hytopia-game |
Each board has its own AB T3 Que, Doing, and Test lists - IDs differ per board. Always look up the correct list ID from TRELLO_BOARDS.md.
Get card with agent field:
# Get card details
bash ~/.claude/scripts/trello-get.sh card CARD_ID | jq '{name, desc}'
# Get agent field (Claude=<TRELLO_FIELD_OPTION_ID_CLAUDE>, Codex=<TRELLO_FIELD_OPTION_ID_CODEX>)
curl -sS "https://api.trello.com/1/cards/CARD_ID/customFieldItems?key=$KEY&token=$TOKEN" | jq -r '.[0].idValue'Prompt must include (NEVER truncate!):
- Title: Full card name
- Description: ENTIRE card description - user wrote detailed prompts there!
- Workflow: git checkout, commit/push, tests, PR
Launch commands:
- Codex:
codex --dangerously-bypass-approvals-and-sandbox - Claude:
claude --dangerously-skip-permissions
Launch sequence (MUST follow):
0. CHECK ACTIVE WORKSPACE FIRST: GET /api/workspaces/active — add worktrees to the workspace the user has open, NOT a random one
- Remove all worktrees:
POST /api/workspaces/remove-worktreefor each - Re-add worktrees with tier:
POST /api/workspaces/add-mixed-worktree(includestartTier) - Start agent: send launch command +
\r - Wait 3 seconds
- Accept the
--dangerously-skip-permissionsprompt: Claude now shows a confirmation prompt on launch — send1+\rto accept it, then wait 2 seconds for Claude to fully initialize - Send FULL prompt (title + ENTIRE description + workflow)
- Send
\rto submit - Move Trello card to Doing list
Add worktree with tier:
curl -sS -X POST http://localhost:$PORT/api/workspaces/add-mixed-worktree \
-H "Content-Type: application/json" \
-d '{
"workspaceId": "zoo-shrimp-game",
"repositoryPath": "/path/to/repo",
"repositoryType": "hytopia-game",
"repositoryName": "zoo-game",
"worktreeId": "work1",
"startTier": 3
}'
# startTier: 1=T1 (focus), 2=T2 (review), 3=T3 (background), 4=T4 (lowest)Link Trello card to session (task record):
curl -sS -X PUT "http://localhost:$PORT/api/process/task-records/session:zoo-game-work1-claude" \
-H "Content-Type: application/json" \
-d '{
"tier": 3,
"ticketProvider": "trello",
"ticketCardId": "CARD_ID",
"ticketBoardId": "BOARD_ID",
"ticketCardUrl": "https://trello.com/c/SHORTLINK",
"ticketTitle": "Card title here"
}'Common mistakes to avoid:
- NEVER truncate/summarize descriptions - user wrote detailed prompts!
- ALWAYS check agent field BEFORE launching (Codex vs Claude)
- Stop-session doesn't fully clear - use remove-worktree + re-add
- Sessions are paired (claude+server) - remove both via worktree
When user says "launch all cards from [list] as Codexes":
1. Get the correct list ID:
KEY=$(awk -F= '/^TRELLO_API_KEY=/{print $2}' ~/.trello-credentials | tr -d '\r\n[:space:]')
TOKEN=$(awk -F= '/^TRELLO_TOKEN=/{print $2}' ~/.trello-credentials | tr -d '\r\n[:space:]')
curl -fsS "https://api.trello.com/1/boards/BOARD_ID/lists?key=${KEY}&token=${TOKEN}" | jq -r '.[] | "\(.id) | \(.name)"'2. Get ALL cards with FULL descriptions:
curl -fsS "https://api.trello.com/1/lists/LIST_ID/cards?key=${KEY}&token=${TOKEN}&fields=id,name,desc" > /tmp/trello-cards.json
# Verify desc lengths (list endpoint may truncate):
jq -r '.[] | {name: .name[0:60], desc_len: (.desc | length)}' /tmp/trello-cards.json3. Add worktrees to current workspace:
for i in $(seq 1 N); do
curl -sS -X POST "http://localhost:$PORT/api/workspaces/add-mixed-worktree" \
-H "Content-Type: application/json" \
-d '{"workspaceId": "WORKSPACE", "repositoryPath": "REPO_PATH", "repositoryType": "hytopia-game", "repositoryName": "REPO_NAME", "worktreeId": "work'$i'", "startTier": 3}'
done4. For each card, launch Codex then send prompt:
SESSION_ID="REPONAME-workN-claude"
# Launch Codex
curl -sS -X POST "http://localhost:$PORT/api/commander/send-to-session" \
-H "Content-Type: application/json" \
-d "{\"sessionId\": \"$SESSION_ID\", \"input\": \"\u0015codex -m gpt-5.3-codex -c model_reasoning_effort=xhigh --dangerously-bypass-approvals-and-sandbox\"}"
sleep 1
curl -sS -X POST "http://localhost:$PORT/api/commander/send-to-session" \
-H "Content-Type: application/json" \
-d "{\"sessionId\": \"$SESSION_ID\", \"input\": \"\r\"}"
sleep 3 # wait for Codex init (only needs 2-3s)
# Send VERBATIM title + desc + system instructions AFTER
PROMPT="${CARD_TITLE}\n\n${CARD_DESC}\n\n---\nSYSTEM INSTRUCTIONS:\n1. git fetch origin master && git checkout master && git pull\n2. git checkout -b feature/BRANCH_SLUG\n3. Read CLAUDE.md and CODEBASE_DOCUMENTATION.md first\n4. Implement everything above verbatim\n5. Clean surgical code, minimal diff\n6. Automated tests following existing patterns\n7. NEVER squash merge\n8. Commit and push regularly\n9. gh pr create when done, include PR link\n10. Run existing tests"
curl -sS -X POST "http://localhost:$PORT/api/commander/send-to-session" \
-H "Content-Type: application/json" \
--data-binary @- << EOF
{"sessionId": "$SESSION_ID", "input": $(echo "$PROMPT" | jq -Rs .)}
EOF
sleep 1
curl -sS -X POST "http://localhost:$PORT/api/commander/send-to-session" \
-H "Content-Type: application/json" \
-d "{\"sessionId\": \"$SESSION_ID\", \"input\": \"\r\"}"Batch launch key rules:
- NEVER summarize card title or description - paste VERBATIM
- Use
gpt-5.3-codexmodel withxhighreasoning - System instructions go AFTER the card content
- Two-request pattern: text first, then
\rseparately - 3s sleep for Codex init (it initializes in ~2-3s, not 15)
- Use
\u0015(Ctrl+U) before Codex command to clear line - Claude
--dangerously-skip-permissionsacceptance: After launching Claude, send1+\rto accept the confirmation prompt, then wait 2s before sending the task prompt
- Claude:
claude --dangerously-skip-permissions - Codex:
codex --dangerously-bypass-approvals-and-sandbox - Codex with explicit model:
codex -m gpt-5.3-codex -c model_reasoning_effort=xhigh --dangerously-bypass-approvals-and-sandbox
ENOTEMPTY error on npm upgrade:
rm -rf ~/.nvm/versions/node/v24.9.0/lib/node_modules/@openai/codex && npm i -g @openai/codex@latest"Model does not exist" errors — Codex needs upgrading:
npm i -g @openai/codex@latest- Config:
~/.codex/config.toml - Global instructions:
~/.codex/AGENTS.md - Fallback filenames (set in config): reads
CLAUDE.mdif noAGENTS.md
git fetch origin --prune
git checkout -b fix/your-feature-name origin/mainNOTE (worktrees): This repo commonly runs as two git worktrees:
~/GitHub/tools/automation/agent-workspace/master(your daily “production” instance)~/GitHub/tools/automation/agent-workspace/agent-workspace-dev(development)
Because main is usually checked out in the master/ worktree, do not try to check out main inside agent-workspace-dev/ (Git will error: “branch 'main' is already used by worktree…”). Always branch from origin/main in dev.
CRITICAL SAFETY: If you are working in agent-workspace-dev/, do not edit, pull, or run commands in the master/ folder unless explicitly requested — that instance may be running on port 3000.
ALSO CRITICAL: If Commander Claude is running FROM master/, NEVER edit files in master/. Even if you revert changes, nodemon will detect the file change and restart the production server, which crashes all active sessions. ALL code changes go in agent-workspace-dev/ on a feature branch, then PR into main. The ONLY exception is if the user explicitly asks you to edit production.
TEST SAFETY (ports):
- Never use port
3000for dev/test runs. - Use
npm run test:e2e:safe(defaults to a dedicated port) for Playwright.
DO NOT:
- ❌ Read any files first
- ❌ Plan tasks first
- ❌ Use TodoWrite first
- ❌ Do ANYTHING else first
ALWAYS run these git commands IMMEDIATELY when starting ANY work!
2. Read CODEBASE_DOCUMENTATION.md - Contains system docs and file locations (READ THE ENTIRE FILE)
When you complete ANY feature or fix, you MUST create a pull request using gh pr create. This is mandatory. Add "Create PR" as your final checklist item to ensure you never forget.
- Always work on fresh branches from updated main
- If
git fetch origin main:mainfails, usegit fetch origin main && git checkout -b feature/name origin/main - Never provide delivery estimates in weeks; provide dependency-ordered execution slices instead.
- Never darken the background when a modal is open.
- Follow existing patterns in the codebase
- Always prefer parameters over magic numbers - use constants or config
- Use JSON files for configuration - prefer config files over hardcoded values
- Use singleton pattern for managers (SessionManager, StatusDetector, etc.)
- Event-driven communication via Socket.IO
- Clean code, simpler is better where possible
- New files: Verify with
lsafter Write tool - Imports: Use
findto check file exists before importing - Methods: Use
rg "methodName.*\("to verify method exists before calling - Quick check:
node --check server/index.jsto catch syntax errors
- Do a quick sanity check before creating PR:
node --check server/index.js(catch syntax errors)- Test the specific feature manually
- Server: Express.js backend with Socket.IO (
server/index.js) - SessionManager: Terminal session management (
server/sessionManager.js) - StatusDetector: Claude Code session monitoring (
server/statusDetector.js) - GitHelper: Git operations and branch management (
server/gitHelper.js) - WorkspaceManager: Multi-workspace orchestration (
server/workspaceManager.js) - WorktreeHelper: Git worktree operations (
server/worktreeHelper.js) - NotificationService: System notifications (
server/notificationService.js) - CommanderService: Top-Level AI orchestration terminal (
server/commanderService.js) - CommandHistoryService: Terminal autosuggestions via shell history (
server/commandHistoryService.js) - Tauri App: Native desktop application (
src-tauri/) - Diff Viewer: Advanced code review tool (
diff-viewer/)
Commander Claude is a special Claude Code instance that runs from the orchestrator master/ directory with knowledge of the entire system. When you ARE Commander Claude (running in this directory or launched from the Commander panel), you have these capabilities.
IMPORTANT: When you first start, greet the user with:
Commander Claude reporting for duty, sir!
Read the full Commander instructions:
cat ~/GitHub/tools/automation/agent-workspace/master/docs/COMMANDER_CLAUDE.mdThe orchestrator port is NOT hardcoded. It comes from .env in your working directory:
PORT=$(grep ORCHESTRATOR_PORT .env | cut -d= -f2)
# Production (master/) = typically 3000, Dev = typically 4000
# All API examples below use $PORT — resolve it before running commandsAll curl examples in this file use $PORT. Never assume 3000 or 4000.
- View All Sessions: See all active Claude sessions across all workspaces
- API:
GET /api/commander/sessions
- API:
- Send Commands to Sessions: Write input to any running session
- API:
POST /api/commander/send-to-sessionwith{ sessionId, input }
- API:
- Orchestrate Work: Coordinate tasks across multiple Claude instances
- Access Project Information: Read workspace configs and status
# Check Commander status
GET /api/commander/status
# Start/Stop/Restart Commander terminal
POST /api/commander/start
POST /api/commander/stop
POST /api/commander/restart
# Start Claude in Commander (yolo mode by default)
POST /api/commander/start-claude { mode: 'fresh'|'continue'|'resume', yolo: true }
# Send input to Commander terminal
POST /api/commander/input { input: "text to send" }
# Get active workspace (which workspace the UI is showing)
GET /api/workspaces/active
# Returns: { id: "workspace-id", name: "Workspace Name" }
# Falls back to persisted config if in-memory state is null
# View all sessions — returns {"sessions":[...]} NOT bare array!
GET /api/commander/sessions
# jq: use '.sessions[]' not '.[]'
# Send to another session
POST /api/commander/send-to-session { sessionId: "...", input: "..." }
# System Recommendations (missing tools, suggested installs)
GET /api/recommendations # returns {"items":[...]}
POST /api/recommendations # {"package","reason","installCmd","category"}
PATCH /api/recommendations/:id # {"status":"installed"|"dismissed"}
DELETE /api/recommendations/:id # remove entirelyWhen a command fails with "not found", POST a recommendation so the user sees it in the UI 🔧 badge:
curl -sS -X POST http://localhost:$PORT/api/recommendations \
-H "Content-Type: application/json" \
-d '{"package":"dos2unix","reason":"CRLF fix for WSL scripts","installCmd":"sudo apt-get install -y dos2unix","category":"apt"}'Focus a Worktree (show only one worktree's terminals):
curl -sS -X POST http://localhost:$PORT/api/commander/execute \
-H "Content-Type: application/json" \
-d '{"command": "focus-worktree", "params": {"worktreeId": "work1"}}'Show All Worktrees (unfocus/reset view):
NOTE: The show-all-worktrees API command is BROKEN (calls non-existent method).
Use the "View All" button in the UI (bottom-left under worktrees list) instead.
Highlight a Worktree (visual highlight without hiding others):
curl -sS -X POST http://localhost:$PORT/api/commander/execute \
-H "Content-Type: application/json" \
-d '{"command": "highlight-worktree", "params": {"worktreeId": "work1"}}'List All Workspaces:
curl -sS http://localhost:$PORT/api/workspaces | jq '.[].name'Get Workspace Details (including worktrees):
curl -sS http://localhost:$PORT/api/workspaces | jq '.[] | select(.name == "Zoo Game")'Switch to Different Workspace:
Use Socket.IO event switch-workspace with workspaceId - handled via the UI primarily.
Add Worktree to Workspace (CORRECT API FORMAT):
DO NOT use path or worktreePath - the API expects these specific parameters:
curl -sS -X POST http://localhost:$PORT/api/workspaces/add-mixed-worktree \
-H "Content-Type: application/json" \
-d '{
"workspaceId": "workspace-id",
"repositoryPath": "/home/<user>/GitHub/games/hytopia/zoo-game",
"repositoryType": "hytopia-game",
"repositoryName": "zoo-game",
"worktreeId": "work1",
"startTier": 3
}'The worktreePath is computed internally as repositoryPath + worktreeId.
Workspaces are stored in ~/.orchestrator/workspaces/. Each workspace has:
config.json: Workspace configuration- Terminal assignments and repository mappings
- Broadcast a message: Loop through sessions and send to each
- Check project status: Read worktree git status via sessions
- Coordinate builds: Trigger builds across multiple projects
CODEBASE_DOCUMENTATION.md: Comprehensive system overviewdocs/COMMANDER_CLAUDE.md: Commander AI API referenceserver/index.js: Main backend entry pointpackage.json: Dependencies and scriptssrc-tauri/src/main.rs: Tauri app entry point
- Multi-Workspace System: Dynamic workspace management with mixed-repo support
- Multi-Terminal Management: Configurable terminal grid (default 16 terminals)
- Native Desktop App: High-performance Tauri-based application
- Advanced Diff Viewer: Web-based code review with AI analysis
- Real-time Communication: Socket.IO for live updates
- Worktree Integration: Seamless git worktree creation and management
- Single-repo workspaces: Traditional one-repository-per-workspace
- Mixed-repo workspaces: Multiple repositories in one workspace via worktrees
- Templates: Predefined workspace configurations in
templates/launch-settings/ - User Settings: Personal preferences stored in
user-settings.json
- Workspace configurations are stored in
~/.orchestrator/workspaces/ - Each workspace can have different terminal counts and repository setups
- Mixed-repo workspaces automatically create worktrees in project directories
- Templates provide consistent setups for different project types
server/workspaceManager.js: Core workspace operationsserver/workspaceSchemas.js: Configuration validationserver/worktreeHelper.js: Git worktree integrationclient/workspace-wizard.js: UI for workspace creation
The orchestrator now supports browser-like tabs for working with multiple workspaces simultaneously. Each tab maintains its own complete state including terminals, sessions, and UI.
Opening Multiple Workspaces:
- Click the + button in the tab bar to open a new workspace
- Each workspace opens in a separate tab
- Tabs persist their complete state when switching
Switching Between Tabs:
- Click any tab to switch to it
- Alt+← / Alt+→ - Navigate to previous/next tab
- Alt+1-9 - Jump directly to tab 1-9
- Alt+N - Open new workspace tab
- Alt+W - Close current tab
Tab Features:
- Terminal content fully preserved when switching tabs
- Notification badges show activity in background tabs (e.g., "Epic Survivors (3)")
- Each tab has its own sidebar showing that workspace's worktrees
- Terminals continue running in background tabs
- No visual glitches or layout shifts when switching
State Isolation: Each tab maintains complete isolation with its own:
- Terminal instances (XTerm.js) and scrollback buffers
- Session data (branch info, status, etc.)
- Sidebar worktree list
- Scroll positions and cursor positions
State Swapping: When switching tabs, the system swaps state between tabs:
- Hide tab: Save terminals/sessions from global manager → tab storage
- Show tab: Restore terminals/sessions from tab storage → global manager
This ensures each tab sees only its own data without cross-contamination.
Critical Implementation:
- Terminals are NEVER destroyed on visibility toggle (use CSS display instead)
- XTerm instances stay attached to same DOM elements
- Global
terminalManager.terminalsis swapped per tab orchestrator.sessionsis swapped per tab
- Don't destroy terminal DOM elements - Use
display: noneinstead ofinnerHTML = '' - State must be swapped - Can't rely on global state persisting across tabs
- Each tab needs its own container - Use
getTerminalGrid()to get correct container - Tab ID must be set before creating terminals - So they register to correct tab
The orchestrator uses a 5-layer cascading configuration system that allows project-specific button configurations, game modes, and common flags to be defined at different hierarchy levels and merged intelligently.
- Global:
~/GitHub/.orchestrator-config.json - Category:
~/GitHub/games/.orchestrator-config.json - Framework:
~/GitHub/games/hytopia/.orchestrator-config.json - Project:
~/GitHub/games/hytopia/games/HyFire2/.orchestrator-config.json - Worktree:
~/GitHub/games/hytopia/games/HyFire2/work1/.orchestrator-config.json(highest priority)
{
"buttons": {
"claude": {
"review": {
"label": "Review",
"command": "gh pr view --web",
"description": "Open PR in browser"
}
},
"server": {
"play": {
"label": "Play",
"command": "npm run dev -- {{gameMode}} {{commonFlags}}",
"description": "Start game server"
}
}
},
"gameModes": {
"deathmatch": {
"flag": "--mode=deathmatch",
"label": "Deathmatch"
}
},
"commonFlags": {
"unlockAll": {
"flag": "--unlock-all",
"label": "Unlock All"
}
}
}- Buttons: Deep merge by terminal type (claude/server) and button ID
- Game Modes: Object merge - child overrides parent with same key
- Common Flags: Object merge - child overrides parent with same key
- Arrays: Child completely replaces parent (no array merge)
- Primitives: Child overrides parent
# Get base config for a repository type
GET /api/cascaded-config/:type
# Get config with worktree overrides
GET /api/cascaded-config/:type?worktreePath=/path/to/worktree// Get base cascaded config
const config = workspaceManager.getCascadedConfigBase('hytopia-game');
// Get config with worktree-specific overrides
const worktreeConfig = await workspaceManager.getCascadedConfigForWorktree(
'hytopia-game',
'/home/user/GitHub/games/hytopia/games/HyFire2/work1'
);- Config Discovery:
server/configDiscoveryService.jsautomatically scans file hierarchy for.orchestrator-config.jsonfiles - Deep Cloning: All configs are deep cloned before merging to prevent cache mutation
- Error Handling: Missing config files at any level are gracefully handled (no crashes)
- Cache Prevention: Uses
JSON.parse(JSON.stringify())to ensure cached configs aren't mutated - Undefined Handling: mergeConfigs uses
{ ...(result[key] || {}), ...override[key] }pattern to safely handle undefined values
- Config Mutation: Always deep clone before merging - shallow spread operators (
{ ...obj }) still share nested references - Undefined Spread: Use
|| {}when spreading to handle undefined gameModes/commonFlags - Master Directory Discovery: For worktree-based projects, configs are discovered in
master/subdirectory - Terminal-Specific Buttons: Each terminal type (claude/server) has its own button namespace
- Array Replacement: Unlike objects, arrays don't merge - child completely replaces parent array
# Development
npm run dev
npm run tauri:dev
# Tauri desktop builds
npm run tauri:build # Release build (slow, optimized, small binary — for distribution)
npm run tauri:build:fast # Fast build (~3-5x faster — for local testing/iteration)
# Single installer format only (even faster):
# node scripts/tauri/prepare-backend-resources.js --install-prod && tauri build -b nsis -- --profile fast
# Testing
node --check server/index.js
# Workspace migration (if needed)
node scripts/migrate-to-workspaces.jsrelease(defaulttauri:build):lto=true,codegen-units=1,opt-level="s"— smallest binary, slowest compile. Use for distribution/CI.fast(tauri:build:fast):lto=false,codegen-units=256,incremental=true— ~3-5x faster compile. Use for local dev/testing.
package.jsonis the single source of truth for the release version.- Keep
src-tauri/tauri.conf.jsonandsrc-tauri/Cargo.tomlsynced withnpm run release:sync-version. - Validate the repo before tagging or building release assets with
npm run release:check-version. - Release tags must be
v<package.json version>. If the tag andpackage.jsondo not match, release CI will fail. scripts/tauri/run-tauri-build.jsclears the profile-specificbundle/output before each build and verifies that every uploaded installer filename includes the expected version. This prevents stale cached assets from being attached to a new GitHub release.
# 1. Bump package.json + package-lock.json
npm version 0.1.8 --no-git-tag-version
# 2. Mirror package version into Tauri/Cargo metadata
npm run release:sync-version
# 3. Verify everything matches before tagging
npm run release:check-version
# 4. Commit the version bump, then tag the exact same version
git add package.json package-lock.json src-tauri/tauri.conf.json src-tauri/Cargo.toml
git commit -m "chore: release 0.1.8"
git tag v0.1.8
git push origin your-branch --follow-tags# 1. Rust (no sudo)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && source "$HOME/.cargo/env"
# 2. System libs (Ubuntu 24.04+ / WSL)
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libayatana-appindicator3-dev
# Ubuntu 22.04: use libwebkit2gtk-4.0-dev instead of 4.1
# 3. Build
npm run tauri:build:fast
# WSL: AppImage fails (no FUSE) — use deb-only instead:
# npx tauri build -b deb -- --profile fastFirst build ~43s, rebuilds ~2-3s (incremental). Needs ~3-5 GB disk.
- Native app provides 10-20x faster startup vs browser
- Use object pooling for frequently created objects
- Limit socket event frequency for performance
- Cache frequently accessed data (session states, git info)
If you haven't already run these commands, STOP and do it NOW:
git fetch origin main:main
git checkout -b feature/new-feature main- ✅ Already done: You've fetched main and created a new branch
- Check existing similar implementations
- Follow established patterns (service-based architecture)
- Commit and push often
- Update documentation if adding new files/systems: Update CODEBASE_DOCUMENTATION.md in a SEPARATE commit BEFORE the main work
- Test the feature thoroughly
- Remove debug logs: Remove any temporary debug logging added for this specific feature/bug
- Run final checks: lint, syntax check, and manual testing
- BEFORE creating a pull request: Update
CODEBASE_DOCUMENTATION.mdif you have added any new files or systems - ALWAYS create a PR when done: Once all changes are committed and pushed, create a pull request using
gh pr create
# Push your branch if not already pushed
git push -u origin your-branch-name
# Create PR with descriptive title and body
gh pr create --title "feat: brief description" --body "$(cat <<'EOF'
## Summary
- What was added/fixed
- Key changes made
## Test plan
- How to test the changes
- Expected behavior
🤖 Generated with [Claude Code](https://claude.ai/code)
EOF
)"🚨 CRITICAL: For related features across components (server/client/tauri), always work on the SAME branch and create ONE PR
- Related features across server/client/tauri
- Building on previous work in same session
- Adding enhancements to existing feature
- Bug fixes + improvements for same system
git checkout -b feature/complete-feature-name main
# Phase 1: Backend changes
git add . && git commit -m "phase 1: backend implementation"
# Phase 2: Frontend changes
git add . && git commit -m "phase 2: frontend integration"
# Phase 3: Native app updates
git add . && git commit -m "phase 3: native app support"
# ONE PR with all phases
git push -u origin feature/complete-feature-name
gh pr create --title "Complete feature with all components"SINGLETONS: SessionManager.getInstance(), service managers
EVENTS: Socket.IO events for real-time communication
GLOBALS: process.env for configuration, global logger
DEBUG: Winston logger with multiple levels and files
CONFIG: config.json for shared settings, .env for secrets
SERVICES: Modular service architecture with clear interfaces
- Socket.IO CORS settings must include all client origins
- Native app requires different handling than web clients
- File watching can be resource intensive - use debouncing
- All managers use singleton pattern for consistency
- Git operations should be async and error-handled
- Logs should use Winston logger, not console.log
- Be careful with
pkill -fcommands - avoid broad patterns that could kill WSL or Claude Code itself - node-pty segfaults: Run
npm rebuild node-ptyif server crashes with segmentation fault - Workspace switching: Clean up all sessions before switching to prevent orphaned processes
- Worktree paths: Validate worktree paths to avoid conflicts with existing directories
- Mixed-repo terminal naming: Use consistent patterns to avoid terminal ID conflicts
- Workspace templates: Always validate against schemas to prevent invalid configurations
- Config cache mutation: Always deep clone configs before merging - use
JSON.parse(JSON.stringify())not shallow spread - Undefined config spread: Handle missing gameModes/commonFlags with
{ ...(result[key] || {}), ...override[key] }pattern - XTerm rendering race: Wrap fitTerminal() in requestAnimationFrame() to allow renderer initialization
- Repository name extraction: For mixed-repo workspaces, use workspace config's terminal.repository.name, not session ID parsing
- ALWAYS check active workspace first: Before adding worktrees or launching agents, call
GET /api/workspaces/activeto find which workspace the user currently has open. Add worktrees to THAT workspace — never guess or pick a workspace by name remove-worktreenukes ALL repos with matching worktreeId:POST /api/workspaces/remove-worktreewith justworktreeId: "work1"removes EVERY repo's work1 in the workspace. ALWAYS scope withrepositoryNameto remove only the intended repo's worktree
To avoid conflicts when developing the Orchestrator itself while using it for other work.
Full installation (Production + Dev instances):
# 1. Production instance (port 3000)
git clone https://github.com/web3dev1337/agent-workspace.git ~/GitHub/tools/automation/agent-workspace/master
cd ~/GitHub/tools/automation/agent-workspace/master
cat > .env << 'EOF'
ORCHESTRATOR_PORT=3000
CLIENT_PORT=2080
TAURI_DEV_PORT=1420
DIFF_VIEWER_PORT=7655
LOG_LEVEL=info
NODE_ENV=development
ENABLE_FILE_WATCHING=true
EOF
npm install
cd diff-viewer && npm install && cd ..
# 2. Dev instance (port 4000)
git clone https://github.com/web3dev1337/agent-workspace.git ~/GitHub/tools/automation/agent-workspace/agent-workspace-dev
cd ~/GitHub/tools/automation/agent-workspace/agent-workspace-dev
cat > .env << 'EOF'
ORCHESTRATOR_PORT=4000
CLIENT_PORT=2081
TAURI_DEV_PORT=1421
DIFF_VIEWER_PORT=7656
LOG_LEVEL=info
NODE_ENV=development
ENABLE_FILE_WATCHING=true
EOF
npm install
cd diff-viewer && npm install && cd ..cd ~/GitHub/tools/automation/agent-workspace/master
npm start # Runs on ports 3000/2080/7655cd ~/GitHub/tools/automation/agent-workspace/agent-workspace-dev
npm start # Runs on ports 4000/2081/7656| Purpose | Directory | Command | Ports | Use Case |
|---|---|---|---|---|
| Production | ~/GitHub/tools/automation/agent-workspace/master | npm start |
3000/2080/7655 | Your daily Claude work |
| Development | ~/GitHub/tools/automation/agent-workspace/agent-workspace-dev | npm start |
4000/2081/7656 | Modifying Orchestrator |
All commands run these 4 services:
- Server (Express backend with hot-reload)
- Client (Web UI dev server)
- Tauri (Native desktop app)
- Diff Viewer (PR review tool on port 7655 for prod, 7656 for dev)
- DO NOT touch the production
master/instance when developing: if you’re working inagent-workspace-dev/(feature branches / PRs), treat~/GitHub/tools/automation/agent-workspace/masteras run-only. Do all code changes + commits inagent-workspace-dev/, then open PRs intomain. Onlygit pullinmaster/when you explicitly want to update the running production copy. - Both instances can run simultaneously without conflicts
- The
.envfiles control which ports are used npm start,npm run dev, andnpm run prodare all equivalent- Each instance needs its own
node_modulesanddiff-viewer/node_modules
🚨 END OF FILE - ENSURE YOU READ EVERYTHING ABOVE 🚨