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.
🔵 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:
- Task creation — User runs a shell command; a
LocalShellTaskinstance is created with statepending. - State transition — The scheduler moves the task to
runningand spawns a child process. - Output capture — stdout and stderr are streamed into the task's output buffer.
- Pill label update —
pillLabel()generates a status badge shown in the REPL status bar. - Process exit — The child process exits with code 0 → state becomes
completed. - Error path — If exit code is non-zero, state becomes
failedwith captured stderr. - Kill path — If user presses Ctrl+C,
stopTask()sends SIGTERM →killed. - Cleanup — Resources (file descriptors, temp dirs) are released regardless of outcome.
- Result return — The REPL reads the final output buffer and displays results.
Key Types & Functions
| Symbol | File | Purpose |
|---|---|---|
TaskState | types.ts | Union type: pending | running | completed | failed | killed |
TaskDescriptor | types.ts | Base interface for all task types with id, state, output |
LocalShellTask | LocalShellTask.ts | Wraps child_process.spawn for bash commands |
LocalAgentTask | LocalAgentTask.ts | Manages local sub-agent lifecycle |
RemoteAgentTask | RemoteAgentTask.ts | Cloud-delegated agent task via bridge |
DreamTask | DreamTask.ts | Background dream/thinking process |
LocalMainSessionTask | LocalMainSessionTask.ts | Wraps the REPL main loop as a task |
stopTask() | stopTask.ts | Graceful termination: SIGTERM → SIGKILL fallback |
pillLabel() | pillLabel.ts | Generates coloured status pill for UI display |
TaskRegistry | registry.ts | Global map of active tasks by ID |
captureOutput() | capture.ts | Streams 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
| Option | Default | Description |
|---|---|---|
TASK_KILL_TIMEOUT_MS | 5000 | Time to wait after SIGTERM before sending SIGKILL |
OUTPUT_BUFFER_MAX_LINES | 10000 | Max lines retained in task output ring buffer |
PILL_REFRESH_INTERVAL_MS | 500 | How often to update status pill labels in the UI |
MAX_CONCURRENT_TASKS | 8 | Maximum tasks running simultaneously |