Feature: Expose background task state to SessionEnd hooks

Resolved 💬 4 comments Opened May 26, 2026 by YogiOneKanobi Closed Jun 26, 2026

Problem

SessionEnd hooks (triggered by /clear) cannot reliably detect whether background tasks are still running. This creates a risk of clearing a session while work is in progress.

Why shell hooks can't see background tasks

  • Process tree walking fails: run_in_background tasks are reparented to PID 1, so they're not in the Claude process tree. A command hook walking pgrep -P will never find them.
  • No filesystem state: Claude tracks background tasks in-memory only. There's no .pid file, status file, or lock file in the task output directory (/tmp/claude-*/tasks/) that a shell script could check.
  • prompt hooks are advisory: A prompt hook on SessionEnd can ask Claude to check TaskList, but it may not get a full execution turn before teardown completes — making it unreliable as a gate.

Current workaround (two-layer, partial coverage)

  1. A command hook that walks the Claude process tree for child processes (catches MCP servers, direct children — but not run_in_background tasks)
  2. A prompt hook asking Claude to check TaskList (advisory only, not a hard gate)

Neither layer reliably catches the common case: a Bash(run_in_background: true) command or a background Agent that hasn't completed yet.

Proposed Solution

One or both of:

Option A: Task-aware hook type

A new hook type (e.g., "type": "task_gate") that automatically blocks the session action if any tasks are in in_progress or pending state. No shell script needed — the runtime checks its own internal state.

{
  "type": "task_gate",
  "blockMessage": "Background tasks are still running. Wait for them to complete or stop them before clearing."
}

Option B: Expose task state to filesystem

Write a .status JSON file alongside each task's .output file (or a single tasks.json summary) that command hooks can read:

{
  "tasks": [
    {"id": "bgz6y9hwq", "status": "completed", "pid": null},
    {"id": "bzt73iz7p", "status": "running", "pid": 12345}
  ]
}

This would let shell hooks do what they're good at — reading files and making exit-code decisions.

Environment

  • Claude Code 2.1.149
  • macOS (Darwin 25.5.0)
  • Hook config: SessionEnd with matcher: "clear"

Context

This came up while building a SessionEnd hook system to ensure clean session teardowns. The guard script works well for OS-level processes but has a fundamental blind spot for Claude's internal task management.

---
Filed by illartech

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗