Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Guide for running local E2E tests with API server, Docker lead/worker containers, task creation, log verification, UI dashboard, and cleanup
Local E2E Testing Guide
Run full end-to-end tests of the agent swarm locally with a real API server and Docker containers.
When to Use This Skill
This skill should be invoked in two modes:
User-requested QA: The user asks you to run E2E tests, verify a feature, or QA a specific flow. Follow the steps below targeting what they asked for.
Automated change verification: After implementing changes that touch the API, runner, polling, task lifecycle, session logs, Docker entrypoint, or worker/lead behavior — use this skill proactively to verify the changes work end-to-end. Determine what's testable based on the diff:
Task lifecycle changes (poll, runner, store-progress): Create assigned + pool tasks, verify they complete and have correct logs
Session log changes: Run two sequential tasks on the same agent, verify log isolation (unique sessionIds, no cross-contamination)
UI changes: Start the dashboard, use agent-browser/qa-use to verify rendering
API endpoint changes: Call the endpoint directly and verify the response
You do not need to run every step — pick the subset relevant to the changes being tested.
Prerequisites
OrbStack or Docker Desktop running (open -a OrbStack if needed)
.env with API_KEY and PORT configured
.env.docker-lead with lead config (AGENT_ID, , )
CLAUDE_CODE_OAUTH_TOKEN
MCP_BASE_URL
.env.docker with worker config (AGENT_ID, CLAUDE_CODE_OAUTH_TOKEN or OPENROUTER_API_KEY, MCP_BASE_URL)
Step 1: Determine Your Port
Check .env for the configured port — do not assume 3013:
grep ^PORT= .env
Use this value as $PORT throughout. In worktrees, each worktree may have a different port. Always verify and use the value from .env.
Also verify the Docker env files match:
grep MCP_BASE_URL .env.docker-lead .env.docker
# Both should point to http://host.docker.internal:$PORT
If they don't match, update them before starting containers.
Step 2: Clean DB + Start API Server
# Kill any existing API process on your port
lsof -ti :$PORT | xargs kill 2>/dev/null
# Clean DB for fresh staterm -f agent-swarm-db.sqlite agent-swarm-db.sqlite-wal agent-swarm-db.sqlite-shm
# Start API server
bun run start:http &
# Wait ~3s for startup, confirm "MCP HTTP server running on http://localhost:$PORT/mcp"
Step 3: Build Docker Image
bun run docker:build:worker:slim
This builds agent-swarm-worker:slim from the current code — the slim target is faster and sufficient for E2E (all four harnesses included). Use bun run docker:build:worker + agent-swarm-worker:latest instead only when the test needs playwright/qa-use, local postgres/redis, or glab. Rebuild after every code change.
Step 4: Start Lead Container
Use a unique container name to avoid conflicts with other worktrees (e.g. include branch name or feature):
Start the dashboard to visually verify tasks, logs, and agent status:
cd apps/ui && bun run dev &
# Defaults to port from APP_URL in .env (check with: grep APP_URL ../.env)
If the UI port is taken by another worktree, start on an alternate:
cd apps/ui && bun run dev --port 5276
The UI connects to the API via VITE_API_URL (check apps/ui/.env or defaults to http://localhost:$PORT).
Visual verification with agent-browser / qa-use
Use agent-browser or qa-use to automate UI checks:
# Quick visual gut-check with agent-browser
agent-browser --url http://localhost:5175 snapshot
# Or use qa-use to verify specific flows
qa-use explore http://localhost:5175
Things to verify in the UI:
Agents page: Lead and worker both show as registered with correct status
Tasks page: Tasks appear with correct status, assigned agent, and timestamps
Task detail → Logs tab: Session logs render in the conversation viewer (not "No session data available")
Task detail → Outcome tab: Completed tasks show output
Costs: Session costs appear for completed tasks
Step 11: Cleanup
# Stop containers (use your branch-specific names)
docker stop e2e-lead-$(git branch --show-current | tr'/''-') e2e-worker-$(git branch --show-current | tr'/''-') 2>/dev/null
# Stop API server
lsof -ti :$PORT | xargs kill 2>/dev/null
# Stop UI dev server (if started)
lsof -ti :5175 | xargs kill 2>/dev/null
Troubleshooting
Docker daemon not running
ERROR: Cannot connect to the Docker daemon
Fix: open -a OrbStack and wait ~5s.
Container name conflict
docker: Error response from daemon: Conflict. The container name "..." is already in use
Another worktree has a container with the same name. Either stop it (docker stop <name>) or use a different name suffix.
Lead not picking up tasks
Verify task was created with agentId (not assignedTo) — wrong param silently creates an unassigned task
Check task status isn't already in_progress (e.g. from a manual poll call that consumed the trigger)
Restart container if stuck: docker restart <container-name>
Worker not picking up pool tasks
Workers auto-claim via poll. Leads do not claim pool tasks.
If "At capacity" — a previous task is still running. Wait or restart.
Poll returns 404
Poll endpoint is GET/api/poll (not POST)
Requires X-Agent-ID header with a valid agent UUID
Port conflicts (worktrees)
lsof -i :3013 # Check what's using the port
If another worktree is running, set a different PORT in .env and update MCP_BASE_URL in .env.docker* to http://host.docker.internal:<new-port>.
Session logs show 0 entries
Task must have actually run (status completed or failed, not just in_progress)
Check claudeSessionId is set on the task: GET /api/tasks/<id> should show it
If logs were stored under wrong taskId, check the session_logs table directly
Task cancellation doesn't stop Claude
Direct API cancellation (POST /api/tasks/<id>/cancel) updates the DB but doesn't kill the Claude process inside Docker. Use docker restart <container> to force-stop.
Keep tasks trivial
Use simple tasks like "Say hello" for E2E tests. Complex tasks waste time and API credits.
UI shows stale data
The dashboard auto-polls every 5 seconds. If data looks stale, hard-refresh (Cmd+Shift+R) or check VITE_API_URL points to the correct API port.