AASC

Session Management

How sessions are tracked, matched, and managed throughout their lifecycle.

Session State Machine#

Every session progresses through a set of statuses driven by hook events:

SessionStart → idle (Robot idles at coffee lounge) UserPromptSubmit → prompting (Robot walks to desk) PreToolUse → working (Robot sits, charging effect) PostToolUse → working (Stays working) [timer expires] → approval (Visor flashes yellow) PermissionRequest → approval (Direct signal, more reliable) Stop → waiting (Robot goes to gym) [2 min idle] → idle (Back to coffee lounge) SessionEnd → ended (Offline animation)

Status Details#

| Status | Animation | 3D Behavior | |--------|-----------|-------------| | idle | Gentle bob | Seeks coffee lounge workstation | | prompting | Head tilt | Walks to desk in assigned room | | working | Charge effect, typing arms | Sits at desk, tool-specific animations | | waiting | Slow bounce | Seeks gym workstation | | approval | Visor flash, arm shake | Freezes in place | | input | Purple visor pulse | Freezes, arm raised | | ended | Dim, head drooped | Stays in last position |

Approval Detection#

Two mechanisms detect when an agent needs user approval:

Timeout Heuristic#

When PreToolUse fires, a category-based timer starts:

| Category | Tools | Timeout | |----------|-------|---------| | fast | Read, Write, Edit, Grep, Glob | 3 seconds | | userInput | AskUserQuestion, EnterPlanMode | 3 seconds | | medium | WebFetch, WebSearch | 15 seconds | | slow | Bash, Task | 8 seconds |

If PostToolUse doesn't arrive before the timeout, the session transitions to approval (or input for userInput tools).

For slow tools, a hasChildProcesses check runs first — if the process still has children, the command is still running and isn't waiting for approval.

PermissionRequest Signal#

At medium+ hook density, the PermissionRequest hook event fires when Claude actually asks for approval. This immediately overrides the timeout heuristic and is more reliable.

Session Matching#

When a hook event arrives with an unknown session_id, the matcher links it to the correct terminal session using a 5-priority fallback:

| Priority | Strategy | When Used | |----------|----------|-----------| | 0 | Pending resume + terminal ID | Session resume after disconnect | | 1 | AGENT_MANAGER_TERMINAL_ID env var | SSH terminal with injected env | | 2 | Working directory match | Claude starts in same dir as terminal | | 3 | Path scan of connecting sessions | Multiple sessions, pick matching dir | | 4 | PID parent check | Check if Claude is child of PTY |

If no match is found, a display-only card is created showing the detected source (VS Code, iTerm, Warp, etc.).

Team & Subagent Tracking#

When Claude spawns agent teams, the dashboard tracks parent-child relationships:

  • Direct linking: CLAUDE_CODE_PARENT_SESSION_ID env var provides instant linkage
  • Path-based detection: SubagentStart on parent + new SessionStart within 10 seconds from matching directory
  • Visual: Animated connection beams between parent and child robots
  • Cleanup: Team is deleted 15 seconds after all members end

Session Resume#

When you resume a Claude session (claude --resume or claude --continue):

  1. A pendingResume entry is registered
  2. The new SessionStart event is matched to the pending entry
  3. The session is re-keyed: old data moves to previousSessions history
  4. Previous prompt history is accessible as collapsible sections in the detail panel
  5. Terminal reconnects automatically

Labels & Organization#

Sessions can be labeled for organization:

| Label | Behavior | |-------|----------| | ONEOFF | Completion alarm + shake effect | | HEAVY | Auto-pinned, urgentAlarm + electric frame on completion | | IMPORTANT | Auto-pinned, fanfare + liquid frame on completion | | Custom | Configurable per-label sound, movement, and frame effects |

Labels persist across session resume and are stored in both the server and IndexedDB.