Skip to content

Lifecycle Events

This document describes Séance's unified lifecycle event system — the hooks that translate agent activity into sidebar status updates.

Overview

All agent integrations ultimately translate to the same set of Séance hooks. Whether the agent uses a TypeScript plugin, shell hooks, or inotifywait monitoring, the end result is the same: seance ctl <agent>-hook <event> commands that update the sidebar.

Agent Integration Types

TypeAgentsHow Events Are Detected
TypeScript pluginOpenCode, Kilo Code, MiMo CodePlugin subscribes to agent's event system
Python pluginHermes AgentPlugin registers callbacks with agent's hook system
Shell hooksClaude CodeHooks injected into ~/.claude/settings.json
TOML config hooksMistral VibeHooks appended to ~/.vibe/hooks.toml
Built-in wrapperCodex, Pi AgentAgent's native hooks call seance ctl directly
Session log monitoringPoolside, Codebuff, Freebuffinotifywait watches for file changes

For detailed documentation on each approach, see:

Séance Hook Events

All integrations translate to these unified hook commands:

HookDescriptionStatus Effect
session-startAgent session startedRunning
prompt-submitUser prompt submitted / agent busyRunning
pre-tool-useTool execution startingRunning
post-tool-useTool execution completedRunning
stopAgent idle, waiting for inputIdle
notificationUser notification neededNeeds input
session-endAgent session ended(cleared)

Additional Hooks

Some agents have custom hooks beyond the standard set:

HookAgentDescription
llm-completeHermesLLM call finished — sets Idle
approval-requestHermesPermission requested — sets Needs input
approval-responseHermesPermission granted/denied — no-op
interruptHermesSession reset via /reset or /new — sets Idle

Hook Payload Format

All hooks receive a JSON payload via stdin:

json
{
  "session_id": "string | null",
  "workspace_id": "string (env SEANCE_WORKSPACE_ID)",
  "surface_id": "string (env SEANCE_SURFACE_ID)",
  "subagent_count": "number",
  "tool_name": "string (pre/post-tool-use only)",
  "message": "string (notification only)"
}

Status Tracking

Main Agent Status

The sidebar shows each agent's current state:

StateMeaningTriggered By
RunningAgent is processingsession-start, prompt-submit, pre-tool-use, post-tool-use
IdleAgent finished, waitingstop, llm-complete (Hermes)
Needs inputWaiting for permissionnotification, approval-request (Hermes)

Status Updates

HookSéance API CallStatus KeyStatus Value
session-startworkspace.set_status{agent}"Running"
prompt-submitworkspace.set_status{agent}"Running"
pre-tool-useworkspace.set_status{agent}"Running"
post-tool-useworkspace.set_status{agent}"Running"
stopworkspace.set_status{agent}"Idle"
notificationworkspace.set_status{agent}"Needs input"
session-endworkspace.clear_status{agent}(removed)

Status Scope

  • Session-level (Claude Code only): Status is shared across all surfaces in a workspace. Two Claude Code sessions show whichever updated last.
  • Per-surface (all other agents): Each terminal pane tracks independently.

Subagent Tracking

Some agents (MiMo Code) spawn subagents. Séance tracks these via:

  1. Detection: Plugin detects subagent via actor.registered event or session ID mismatch
  2. Counting: Plugin maintains subagentCount and backgroundCount
  3. Reporting: Plugin sends subagent-update command with counts
  4. Display: Sidebar shows activity indicators based on counts
json
{
  "workspace_id": "string",
  "subagent_count": "number",
  "background_count": 0
}

Activity Indicators

Subtasks ActiveBackground ActiveIconMeaning
NoNoNormalAgent running, no subagents
YesNosystem-run-symbolicSubagents actively working
NoYesmedia-playback-start-symbolicBackground tasks running
YesYessystem-run-symbolicSubtasks take precedence

Subagent Status Flow

Agent spawns subagent
  → Plugin detects via actor.registered or session ID mismatch
  → Plugin increments subagentCount
  → Plugin sends subagent-update
  → Sidebar shows subagent indicator

Subagent completes
  → Plugin detects via actor.status (idle) or session end
  → Plugin decrements subagentCount
  → Plugin sends subagent-update
  → Sidebar updates indicator

Deltas and Drift

Critical Differences Between Agents

1. Status Key Mode

Claude uses session mode; all others use surface mode.

zig
const claude_agent = AgentConfig{
  .status_key_mode = .session,  // Shared across workspace
};

const opencode_agent = AgentConfig{
  .status_key_mode = .surface,  // Per-surface
};

2. Notification Support

AgentNotification Support
Claude CodeYes (notification hook)
CodebuffNo
CodexNo
FreebuffNo
Hermes AgentCustom (approval-request)
Kilo CodeYes (notification hook)
MiMo CodeYes (notification hook)
Mistral VibeNo
OpenCodeYes (notification hook)
Pi AgentNo
Poolside Agent CLINo

3. Status Clearing on Session End

Most agents clear status on session-end. Hermes does not — it uses llm-complete for idle detection because sessions outlive individual agent processes.

Agentclear_status_on_end
Claude CodeYes
CodebuffYes
CodexYes
FreebuffYes
Hermes AgentNo
Kilo CodeYes
MiMo CodeYes
Mistral VibeYes
OpenCodeYes
Pi AgentYes
Poolside Agent CLIYes

MIT Licensed