tasks — Background Task Management

Background Task Management

Manages the full lifecycle of background tasks including shell commands, sub-agents, cloud agents, and dream processes. Provides unified status tracking, output capture, and graceful termination across all task types.

12
Files
3k
Lines
5
Task Types
TS
TypeScript

🔵 Task Lifecycle 🟢 5 Task Types 🟡 Output Capture 🔴 Sub-Agents

📚 What is this?

The tasks module is the background job scheduler for Claude Code. When you run a shell command, spawn a sub-agent, or kick off a cloud task, this module tracks it through a well-defined state machine (pending → running → completed/failed/killed), captures output, and provides UI pill labels for the REPL status bar.

💡 Analogy

Think of the tasks module as an air-traffic control tower. Each task is an aircraft: LocalShellTask is a small prop plane (bash command), LocalAgentTask is a passenger jet (sub-agent), RemoteAgentTask is a satellite-linked drone (cloud agent), and DreamTask is a weather balloon (background dream). The tower tracks all of them on its radar (TaskState), assigns runways (pending → running), and handles emergency landings (stopTask).

Architecture

flowchart LR
  subgraph TaskTypes["Task Types"]
    LST["LocalShellTask"]
    LAT["LocalAgentTask"]
    RAT["RemoteAgentTask"]
    DT["DreamTask"]
    LMST["LocalMainSessionTask"]
  end
  subgraph Core["Core"]
    TS["types.ts / TaskState"]
    ST["stopTask.ts"]
    PL["pillLabel.ts"]
  end
  subgraph REPL["REPL Integration"]
    SB["Status Bar"]
    TL["Task List View"]
  end
  LST --> TS
  LAT --> TS
  RAT --> TS
  DT --> TS
  LMST --> TS
  TS --> PL
  PL --> SB
  TS --> TL
  ST --> LST
  ST --> LAT
  ST --> RAT
  ST --> DT

Data Flow: Task Status Machine

flowchart TD
  CREATE["Task Created"] --> PENDING["pending"]
  PENDING --> RUNNING["running"]
  RUNNING --> COMPLETED["completed"]
  RUNNING --> FAILED["failed"]
  RUNNING --> KILLED["killed"]
  RUNNING -->|output event| CAPTURE["Output Capture"]
  CAPTURE --> RUNNING
  KILLED -->|stopTask()| CLEANUP["Cleanup Resources"]
  FAILED --> CLEANUP
  COMPLETED --> RESULT["Return Result"]
  CLEANUP --> RESULT
  RESULT --> PILL["pillLabel() → UI"]

🚶 Step-by-Step Walkthrough: Running a LocalShellTask

Trace a bash command from creation to completion:

  1. Task creation — User runs a shell command; a LocalShellTask instance is created with state pending.
  2. State transition — The scheduler moves the task to running and spawns a child process.
  3. Output capture — stdout and stderr are streamed into the task's output buffer.
  4. Pill label update — pillLabel() generates a status badge shown in the REPL status bar.
  5. Process exit — The child process exits with code 0 → state becomes completed.
  6. Error path — If exit code is non-zero, state becomes failed with captured stderr.
  7. Kill path — If user presses Ctrl+C, stopTask() sends SIGTERM → killed.
  8. Cleanup — Resources (file descriptors, temp dirs) are released regardless of outcome.
  9. Result return — The REPL reads the final output buffer and displays results.

Key Types & Functions

SymbolFilePurpose
TaskStatetypes.tsUnion type: pending | running | completed | failed | killed
TaskDescriptortypes.tsBase interface for all task types with id, state, output
LocalShellTaskLocalShellTask.tsWraps child_process.spawn for bash commands
LocalAgentTaskLocalAgentTask.tsManages local sub-agent lifecycle
RemoteAgentTaskRemoteAgentTask.tsCloud-delegated agent task via bridge
DreamTaskDreamTask.tsBackground dream/thinking process
LocalMainSessionTaskLocalMainSessionTask.tsWraps the REPL main loop as a task
stopTask()stopTask.tsGraceful termination: SIGTERM → SIGKILL fallback
pillLabel()pillLabel.tsGenerates coloured status pill for UI display
TaskRegistryregistry.tsGlobal map of active tasks by ID
captureOutput()capture.tsStreams stdout/stderr into ring buffer

Directory Map

Source tree for tasks
tasks/
├── types.ts                     ← TaskState, TaskDescriptor interfaces
├── LocalShellTask.ts            ← Bash command task wrapper
├── LocalAgentTask.ts            ← Sub-agent task manager
├── RemoteAgentTask.ts           ← Cloud agent task via bridge
├── DreamTask.ts                 ← Background dream process
├── LocalMainSessionTask.ts      ← REPL main loop wrapper
├── stopTask.ts                  ← Graceful termination logic
├── pillLabel.ts                 ← UI status pill generator
├── registry.ts                  ← Active task registry (Map)
├── capture.ts                   ← Output stream capture
├── __tests__/
│   ├── LocalShellTask.test.ts
│   ├── stopTask.test.ts
│   └── pillLabel.test.ts
└── index.ts                     ← Barrel export

Configuration

OptionDefaultDescription
TASK_KILL_TIMEOUT_MS5000Time to wait after SIGTERM before sending SIGKILL
OUTPUT_BUFFER_MAX_LINES10000Max lines retained in task output ring buffer
PILL_REFRESH_INTERVAL_MS500How often to update status pill labels in the UI
MAX_CONCURRENT_TASKS8Maximum tasks running simultaneously