asyncRewake blocks session startup instead of running in background (docs say "Implies async") — 2.1.246

Status Open
Reported on v2.1.246
Maintainer reply None cached
Activity 0 comments · opened Aug 27, 2026

Summary

A SessionStart command hook declared with "asyncRewake": true blocks session
startup for the full duration of the hook, instead of running in the background.

The hooks reference documents asyncRewake as:

If true, runs in the background and wakes Claude on exit code 2. Implies async.

Measured behavior does not match: async: true returns immediately, but
asyncRewake: true blocks just like a plain synchronous hook.

Environment

  • Claude Code 2.1.246 (CLI on PATH)
  • Windows 11, PowerShell 7
  • Reproduced in headless mode (claude -p)

Reproduction

Three otherwise identical projects. Each has a SessionStart hook running a
script that sleeps 75s, writes start/end timestamps to a log, prints a marker to
stdout, and exits (exit code 2 for the asyncRewake variant).

{
  "hooks": {
    "SessionStart": [
      { "matcher": "startup", "hooks": [
        { "type": "command",
          "command": "pwsh -NoProfile -File C:\tmp\probe\hook.ps1",
          "shell": "powershell",
          "timeout": 240,
          "asyncRewake": true }
      ]}
    ]
  }
}

Then, in each project directory:

claude -p "reply with one word" --permission-mode bypassPermissions

Results

| Hook config | Wall clock until reply | Hook ran to completion | Marker visible to the model |
|---|---|---|---|
| (no flag) | 83.1s | yes (75.0s) | yes |
| "async": true | 6.0s | ran in background | no (expected) |
| "asyncRewake": true | 82.3s | yes (75.0s) | no |

Expected vs actual

Expected: asyncRewake: true returns control immediately (as async: true
does), runs the hook in the background, and wakes Claude on exit code 2.

Actual: startup blocks for the full 75s hook duration. The exit-code-2 wake
also did not surface the hook output to the model, though that part may be
specific to one-shot -p mode — the blocking is the reproducible part.

Why it matters

async: true works correctly and is a good fit for background startup work.
asyncRewake looked like the right tool when the background work still needs to
report something back, but because it blocks, adopting it silently reintroduces
the startup cost it is supposed to remove.

Note for anyone hitting this: in the VS Code extension a slow SessionStart
hook causes Subprocess initialization did not complete within 60000ms and the
session dies, while the hook itself keeps running to completion. The CLI and the
desktop app have no such deadline. So a hook that blocks is far more damaging on
that surface than the others.

View original on GitHub ↗