anthropics / anthropics/claude-agent-sdk-typescript
PermissionRequest hook never fires under permissionMode: 'default', even though PreToolUse does
- 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.