anthropics / anthropics/claude-agent-sdk-typescript

PermissionRequest hook never fires under permissionMode: 'default', even though PreToolUse does

Open
#435 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Shell
Stars
1.8k
Forks
226
PR merge metrics
No merged PRs in 30d

Description

## Environment

- `@anthropic-ai/claude-agent-sdk`: reproduced on `0.3.220` (originally found), re-confirmed on `0.3.246`, `0.3.247`, and just now on the current latest, `0.3.251`
- `claude` CLI: `2.1.246`
- OS: macOS
- Auth: `claude.ai` subscription session (via `claude setup-token`), not a raw `ANTHROPIC_API_KEY`

## Summary

The native `PermissionRequest` hook never fires for a real tool call under `permissionMode: 'default'`, even though `PreToolUse` fires correctly for the same call. This makes it impossible to build a permission-approval UI on top of the SDK's own hook interface — there's no way to intercept and answer a pending permission decision.

## Minimal reproduction

```js
import { query } from '@anthropic-ai/claude-agent-sdk';

const seen = [];

const result = query({
prompt: 'Write a file named /tmp/permission-repro-test.txt containing the word hello. Use the Write tool.',
options: {
permissionMode: 'default',
cwd: '/tmp',
hooks: {
PreToolUse: [{ hooks: [async (input) => {
seen.push({ hook: 'PreToolUse', toolName: input.tool_name });
return {};
}] }],
PermissionRequest: [{ hooks: [async (input) => {
seen.push({ hook: 'PermissionRequest', toolName: input.tool_name });
return {};
}] }],
},
},
});

for await (const message of result) {
if (message.type === 'result') break;
}

console.log(JSON.stringify(seen, null, 2));
```

No other dependencies — a bare `query()` call, `PreToolUse` and `PermissionRequest` hooks, `permissionMode: 'default'`, a single Write tool call.

## Actual behavior

```json
[
{
"hook": "PreToolUse",
"toolName": "Write"
}
]
```

`PreToolUse` fires. `PermissionRequest` never fires. The Write tool call never executes — Claude replies with an apologetic text message instead of writing the file, and no permission-approval mechanism (native or otherwise) is ever invoked.

## Expected behavior

With `permissionMode: 'default'` and no `canUseTool` callback / no interactive terminal, a blocked tool call should surface via the `PermissionRequest` hook so a host application can programmatically approve or deny it. This is the entire point of that hook's existence per the SDK's own documented hook list.

## Additional notes

- This SDK's own `CHANGELOG.md` claims at `0.2.21`: "Fixed PermissionRequest hooks not being executed in SDK mode (e.g., VS Code extension)." That version predates every version this was reproduced on (`0.3.220` through `0.3.251`), so either the fix regressed or never actually covered this exact code path.
- Isolated with a minimal, dependency-free repro (no Fastify, no session manager, no third-party adapter) to rule out a wiring bug on our own side before filing this — confirmed the gap is in the SDK itself.
- `PreToolUse` firing correctly for the same call rules out a general hooks-wiring problem; only `PermissionRequest` specifically fails to fire.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.