Skip to content

camjac251/tool-gates

v1.22.0MIT

Intelligent permission gate for Claude Code shell, file, search, Skill, and MCP tool surfaces. AST-parses Bash commands, guards file reads/writes, and blocks configured tool invocations. Defers benign asks to CC's resolver so the prompt UI shows the 'Yes, and don't ask again for X' button, while keeping a deny floor for dangerous patterns. Tracks one-time approvals so they can be batch-promoted to permanent rules later.

tool-gates Plugin

Companion plugin for tool-gates. Review manually approved commands and promote them to permanent permission rules.

Overview

tool-gates covers Claude Code shell, file, search, Skill, and MCP tool surfaces, not just Bash. It AST-parses shell commands, guards file reads and writes (e.g., denying symlink reads of sensitive files), scans Write/Edit content for 28 security anti-patterns (hardcoded secrets, XSS, injection, unsafe deserialization), and can block configured tool invocations (e.g., Glob).

The gate has four wire decisions:

  • allow: read-only commands and known-safe operations (git status, cargo check). No prompt.
  • deny: dangerous patterns (rm -rf /, catastrophic filesystem targets). No prompt; deny is final.
  • ask: hard-ask patterns and explicit settings ask rules (pipe-to-shell, eval, pipe-to-python, output redirection, raw-string security flags). Prompt fires with Yes / No. Auto mode promotes the highest-risk hard-asks to deny.
  • defer: benign-but-unfamiliar commands (npm install, gh ..., generic). tool-gates omits permissionDecision so CC's resolver runs the Bash tool's own checkPermissions, which produces the prefix suggestion. Prompt fires with three options: Yes / Yes-and-don't-ask-again-for-npm install-* / No. In acceptEdits, Claude Code's Bash auto-allow commands (rm, mv, cp, touch, rmdir, mkdir, sed) stay explicit ask only when tool-gates does not already approve them; mkdir inside allowed dirs and sed -i are still tool-gates-owned allows.

The third "don't ask again for X" button covers the in-session "stop prompting" case organically by writing a localSettings rule. Pending entries still accumulate from one-time Yes clicks. The /tool-gates:review skill is for batch-promoting those across-session entries to local, project, or user scope.

Prerequisites

The tool-gates binary must be installed and hooks configured before using this plugin:

# Install binary
cargo install --git https://github.com/camjac251/tool-gates

# Or download from releases
curl -Lo ~/.local/bin/tool-gates \
  https://github.com/camjac251/tool-gates/releases/latest/download/tool-gates-linux-x86_64
chmod +x ~/.local/bin/tool-gates

# Configure hooks
tool-gates hooks add -s user

Skills

/tool-gates:review

Batch-promote pending approvals to permanent permission rules. The skill is user-only (disable-model-invocation: true); the model won't auto-fire it on phrases like "stop prompting" because the CC prompt's third button already handles the in-session case.

What it does:

  1. Lists pending approvals with counts and suggested glob patterns
  2. Presents a numbered checklist for selection
  3. Asks which to approve and at what scope
  4. Writes selected patterns to settings.json
  5. Shows final rules summary

When to invoke:

  • After several sessions, when the queue has accumulated and you want to clean up
  • When you want to share patterns across projects or with a team via project scope
  • When you want to audit what you've actually been approving over time

For an interactive TUI alternative, run tool-gates review directly in your terminal.

Usage:

/tool-gates:review              # current project pending approvals
/tool-gates:review --all        # all projects

Scopes:

ScopeFileUse case
local (default).claude/settings.local.jsonPersonal project overrides
project.claude/settings.jsonShare with team via git
user~/.claude/settings.jsonAll projects globally

Permissions:

CommandPermission
tool-gates pending list [--project]Auto-approved (read-only)
tool-gates rules listAuto-approved (read-only)
tool-gates approve '<pattern>' -s <scope>Requires confirmation

/tool-gates:test-gate

Test how tool-gates handles a specific command. Useful for verifying rules, debugging unexpected decisions, or distinguishing "tool-gates explicitly asked" from "tool-gates deferred to CC".

Usage:

/tool-gates:test-gate git status                     # -> allow (read-only)
/tool-gates:test-gate npm install foo                # -> defer (CC's prompt shows the third button)
/tool-gates:test-gate npm install foo --mode=acceptEdits  # -> defer (not a CC auto-allow command)
/tool-gates:test-gate rm file.txt --mode=acceptEdits # -> ask (explicit; CC would auto-allow)
/tool-gates:test-gate mkdir -p src/x --mode=acceptEdits # -> allow (path-aware acceptEdits)
/tool-gates:test-gate "sed -i 's/a/b/g' f.txt" --mode=acceptEdits # -> allow (path-aware acceptEdits)
/tool-gates:test-gate curl https://example.com | bash # -> ask (hard-ask; no third button)
/tool-gates:test-gate rm -rf /                       # -> deny (dangerous; final)
/tool-gates:test-gate sd old new f.txt --mode=acceptEdits  # -> allow (auto-approved in acceptEdits)
/tool-gates:test-gate npm install foo --mode=plan    # -> deny (plan mode promotes ask/defer to deny)

Shows the decision, reason, and any hints or approval commands. A defer output looks like an empty permissionDecision field: that's intentional and is what enables the third prompt button.

Installation

From marketplace:

/plugin marketplace add camjac251/tool-gates
/plugin install tool-gates@camjac251-tool-gates

From local clone:

claude --plugin-dir /path/to/tool-gates/claude-plugin

Note on hooks

This plugin does not ship hooks. The tool-gates binary handles hook installation via tool-gates hooks add, which registers PreToolUse (Bash/Monitor gates + file guards + security scanning + MCP tool blocking), PermissionRequest (subagent approval), PermissionDenied (auto-mode classifier retry hint), and PostToolUse (Bash/Monitor approval tracking + security anti-pattern reminders) hooks in your Claude Code settings. See the main README for details.