[FEATURE] Dynamic Tool Permissions with a canUseTool Hook for the CLI
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Background & Problem Statement
The current tool permission system for the Claude Code CLI, based on static allow/deny lists in settings.json, is excellent for establishing baseline security and reducing prompts for common, safe commands.
However, this static approach has limitations. It cannot adapt to the context of a session, leading to a trade-off: users must either create overly permissive rules or face repetitive permission prompts for actions that are safe under specific, verifiable conditions. This creates friction and "prompt fatigue."
The TypeScript SDK has already introduced a powerful solution to this problem: the canUseTool callback. This feature request is to bring an equivalent mechanism to the interactive CLI, enabling dynamic, programmatic control over tool execution.
Proposed Solution
Proposed Feature: A Dynamic Permission Hook
I propose the introduction of a new, special-purpose hook that acts as a dynamic permission gate. This hook would be a JavaScript or TypeScript script that runs before any tool is executed. Its purpose would be to programmatically decide whether to allow or deny the tool call, and even to modify the tool's input before execution.
This would effectively bring the full power of the SDK's canUseTool callback to all CLI users.
---
Suggested Implementation
A new key, such as permissions.dynamicHook, could be added to the .claude/settings.json file to specify the path to a permission script.
Example .claude/settings.json configuration:
{
"permissions": {
"dynamicHook": "./.claude/hooks/permission-gate.js",
"allow": [
"Read"
]
}
}
Note: Static allow/deny rules could still apply for tools not handled by the dynamic hook, or as a fallback.
The script specified (e.g., permission-gate.js) would export a single async function. This function would receive the toolName and input object as arguments and must return a JSON object that dictates the outcome.
Expected Script Signature and Return Value:
The script would implement a function with a signature like async function(toolName, input). It should return an object with the following structure:
{ "behavior": "allow", "updatedInput": <optional_modified_input_object> }: Approves the tool use. IfupdatedInputis provided, Claude Code will use it instead of the original input.{ "behavior": "deny", "message": "<optional_reason_string>" }: Blocks the tool use. The optionalmessageis shown to the user and fed back to the model as context.
If the script returns nothing or a differently structured object, Claude Code could fall back to the standard permission flow (static rules and user prompts).
Alternative Solutions
_No response_
Priority
Low - Nice to have
Feature Category
CLI commands and flags
Use Case Example
Key Benefits & Use Cases
This feature would unlock a new level of intelligent, context-aware control over the agent's behavior.
- Dynamic Guardrails: Implement sophisticated security or cost-control policies that adapt to the current context.
- Example: A script could check the current
git branchand deny anygit push --forcecommands onmainorproductionbranches. - Example: It could track the session's total cost and deny expensive API calls (via MCP tools) or web searches if a predefined budget is exceeded.
- Input Sanitization and Modification: Programmatically enforce safety and best practices by modifying tool inputs on the fly.
- Example: Automatically add the interactive
-iflag to anyrmcommand to prevent accidental file deletion, as shown in the code concept:input.command.replace('rm ', 'rm -i '). - Example: Enforce a
timeouton potentially long-runningBashcommands.
- Enterprise Control: An organization could deploy a managed
permission-gate.jsscript viamanaged-settings.json. This would enforce complex, company-wide policies that are impossible to represent with static allow/deny lists, such as requiring a JIRA ticket number in all commit messages.
- Improved User Experience: Reduce interruptions by codifying the decision-making process for tool permissions. Users could write a script that automatically approves tool use in specific directories or for non-sensitive file types, eliminating repetitive prompts without creating overly broad static rules.
Additional Context
Bringing a canUseTool equivalent to the CLI would be a paradigm shift from static rule enforcement to intelligent, programmatic policy management, significantly enhancing the safety, efficiency, and power of Claude Code for all users.
Thank you for your consideration.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗