npx claudepluginhub evaneos/agent-callablePreToolUse hook — automatically validates Bash commands against a deny-by-default policy before execution
Tired of endless prompts from Claude Code?
Do you want to proceed?
❯ 1. Yes
2. Yes, and don't ask again for this risk-free command
3. No
My job has turned into approving Claude in a loop across a bunch of split terminals. Yes. Tab. Yes. Tab. Yes. Oops — no, that one was actually a question it was asking me. You know the drill.
On the other hand, I don't feel lucky enough to drop all permissions and let any command run. I want Claude to stop asking me to approve harmless commands — or commands with harmless side effects (yes, you can create a file in my workspace, that's kind of the point). But when it's about to do something truly stupid ("oh right, if I had run that command it would have wiped all your prod data"), I want the normal Claude prompt back.
Claude Code has a built-in, well-documented mechanism for this: allowlists in the settings. But the granularity is not great. Allowing Bash(kubectl get:*) lacks precision on subcommands and fails to match kubectl -c foobar get pod.
agent-callable grew out of kubectl-readonly, a kubectl wrapper that only allows read-only operations. The kubectl policy engine (kubepolicy) proved useful enough that I generalized the approach to cover every CLI tool an agent might call. agent-callable imports kubepolicy directly for its kubectl filtering — same battle-tested rules, broader scope.
agent-callable is two things:
The result: with my agent-callable config, Claude Code no longer prompts me for anything I consider risk-free. Everything else gets the normal prompt. It's 100% transparent.
No security guarantee. This tool filters commands to reduce accidental side effects from LLM agents. It is not a sandbox, does not isolate processes, and a determined or creative agent may find ways around it. Use it as a convenience layer, not as a security boundary.
go install github.com/evaneos/agent-callable/cmd/agent-callable@latest
Then generate the default config:
agent-callable --init-config # creates ~/.config/agent-callable/
The binary is usable standalone at this point — any LLM agent can call agent-callable <command> to run filtered commands.
Add the marketplace and install the plugin:
/plugin marketplace add Evaneos/agent-callable
/plugin install agent-callable@Evaneos/agent-callable
That's it — every Bash command now goes through the filter, no allowlist to maintain, no CLAUDE.md to write.
The plugin installs a PreToolUse hook. Every time Claude is about to run a Bash command, the hook quietly calls agent-callable under the hood:
agent-callable --claudeThe hook never blocks anything itself. It just fast-tracks the boring stuff.
Set AGENT_CALLABLE_HOOK_DEBUG=1 to log hook decisions to /tmp/agent-callable-hook.log.
Outside Claude Code — or in any context where an LLM runs shell commands — the agent prefixes its commands with agent-callable:
agent-callable kubectl get pods -A # allowed
agent-callable git push # blocked
agent-callable --sh 'git log | head -5' # compound shell expression
This requires telling the agent to use the prefix (via CLAUDE.md or equivalent — see SAMPLE_CLAUDE.md). The plugin is simpler since it requires no instructions.
Three categories of side effects:
| Category | Verdict | Examples |
|---|---|---|
| Remote effect — modifies an external service | blocked | git push, kubectl apply, gh pr create |
| Persistent config change — durably alters a tool's behavior | blocked | helm repo add, gcloud config set |
| Local cache/artifact write — useful for investigation | allowed | git fetch, docker pull, gh repo clone |
The rule is simple: when in doubt, block. A false positive (unnecessary prompt) is annoying. A false negative (wiped prod database) is not.