{"id":34632409,"url":"https://github.com/camjac251/bash-gates","last_synced_at":"2026-03-09T20:14:52.709Z","repository":{"id":328739280,"uuid":"1116518235","full_name":"camjac251/bash-gates","owner":"camjac251","description":"Intelligent bash command permission gates for Claude Code using tree-sitter AST parsing","archived":false,"fork":false,"pushed_at":"2026-02-24T10:46:49.000Z","size":672,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-24T13:48:37.480Z","etag":null,"topics":["bash","claude-code","cli","hooks","rust","security","tree-sitter"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/camjac251.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-12-15T01:53:24.000Z","updated_at":"2026-02-24T07:39:26.000Z","dependencies_parsed_at":"2026-01-23T21:00:28.690Z","dependency_job_id":null,"html_url":"https://github.com/camjac251/bash-gates","commit_stats":null,"previous_names":["camjac251/bash-gates"],"tags_count":63,"template":false,"template_full_name":null,"purl":"pkg:github/camjac251/bash-gates","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/camjac251%2Fbash-gates","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/camjac251%2Fbash-gates/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/camjac251%2Fbash-gates/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/camjac251%2Fbash-gates/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/camjac251","download_url":"https://codeload.github.com/camjac251/bash-gates/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/camjac251%2Fbash-gates/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29815020,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-25T05:36:42.804Z","status":"ssl_error","status_checked_at":"2026-02-25T05:36:31.934Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bash","claude-code","cli","hooks","rust","security","tree-sitter"],"created_at":"2025-12-24T16:53:29.178Z","updated_at":"2026-03-09T20:14:52.695Z","avatar_url":"https://github.com/camjac251.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# bash-gates\n\n**Intelligent permission gates for bash commands in Claude Code**\n\n[![CI](https://github.com/camjac251/bash-gates/actions/workflows/ci.yml/badge.svg)](https://github.com/camjac251/bash-gates/actions/workflows/ci.yml)\n[![Release](https://github.com/camjac251/bash-gates/actions/workflows/release.yml/badge.svg)](https://github.com/camjac251/bash-gates/actions/workflows/release.yml)\n[![Rust](https://img.shields.io/badge/rust-1.85+-orange.svg)](https://www.rust-lang.org/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n\nA Claude Code [PreToolUse hook](https://code.claude.com/docs/en/hooks#pretooluse) that analyzes bash commands using AST parsing and determines whether to allow, ask, or block based on potential impact.\n\n[Installation](#installation) · [Permission Gates](#permission-gates) · [Security](#security-features) · [Testing](#testing)\n\n\u003c/div\u003e\n\n---\n\n## Features\n\n| Feature                  | Description                                                                                            |\n| ------------------------ | ------------------------------------------------------------------------------------------------------ |\n| **Approval Learning**    | Tracks approved commands and saves patterns to settings.json via TUI or CLI                            |\n| **Settings Integration** | Respects your `settings.json` allow/deny/ask rules - won't bypass your explicit permissions            |\n| **Accept Edits Mode**    | Auto-allows file-editing commands (`sd`, `prettier --write`, etc.) when in acceptEdits mode            |\n| **Modern CLI Hints**     | Suggests modern alternatives (`bat`, `rg`, `fd`, etc.) via `additionalContext` for Claude to learn     |\n| **AST Parsing**          | Uses [tree-sitter-bash](https://github.com/tree-sitter/tree-sitter-bash) for accurate command analysis |\n| **Compound Commands**    | Handles `\u0026\u0026`, `\\|\\|`, `\\|`, `;` chains correctly                                                       |\n| **Security First**       | Catches pipe-to-shell, eval, command injection patterns                                                |\n| **Unknown Protection**   | Unrecognized commands require approval                                                                 |\n| **Claude Code Plugin**   | Install as a plugin with the `/bash-gates:review` skill for interactive approval management            |\n| **300+ Commands**        | 13 specialized gates with comprehensive coverage                                                       |\n| **Fast**                 | Static native binary, no interpreter overhead                                                          |\n\n---\n\n## How It Works\n\n```mermaid\nflowchart TD\n    CC[Claude Code] --\u003e CMD[Bash Command]\n\n    subgraph PTU [PreToolUse Hook]\n        direction TB\n        PTU_CHECK[bash-gates check] --\u003e PTU_DEC{Decision}\n        PTU_DEC --\u003e|dangerous| PTU_DENY[deny]\n        PTU_DEC --\u003e|risky| PTU_ASK[ask + track]\n        PTU_DEC --\u003e|safe| PTU_CTX{Context?}\n        PTU_CTX --\u003e|main session| PTU_ALLOW[allow ✓]\n        PTU_CTX --\u003e|subagent| PTU_IGNORED[ignored by Claude]\n    end\n\n    CMD --\u003e PTU\n    PTU_IGNORED --\u003e INTERNAL[Claude internal checks]\n    INTERNAL --\u003e|path outside cwd| PR_HOOK\n\n    subgraph PR_HOOK [PermissionRequest Hook]\n        direction TB\n        PR_CHECK[bash-gates re-check] --\u003e PR_DEC{Decision}\n        PR_DEC --\u003e|safe| PR_ALLOW[allow ✓]\n        PR_DEC --\u003e|dangerous| PR_DENY[deny]\n        PR_DEC --\u003e|risky| PR_PROMPT[show prompt]\n    end\n\n    PTU_ASK --\u003e EXEC[Command Executes]\n    PR_PROMPT --\u003e USER_APPROVE[User Approves] --\u003e EXEC\n\n    subgraph POST [PostToolUse Hook]\n        direction TB\n        POST_CHECK[check tracking] --\u003e POST_DEC{Tracked + Success?}\n        POST_DEC --\u003e|yes| PENDING[add to pending queue]\n        POST_DEC --\u003e|no| POST_SKIP[skip]\n    end\n\n    EXEC --\u003e POST\n    PENDING --\u003e REVIEW[bash-gates review]\n    REVIEW --\u003e SETTINGS[settings.json]\n```\n\n**Why three hooks?**\n\n- **PreToolUse**: Gates commands for main session, tracks \"ask\" decisions\n- **PermissionRequest**: Gates commands for subagents (where PreToolUse's `allow` is ignored)\n- **PostToolUse**: Detects successful execution, queues for permanent approval\n\n\u003e `PermissionRequest` metadata like `blocked_path` and `decision_reason` is optional in Claude Code payloads. bash-gates treats those fields as best-effort context, not required inputs.\n\n**Decision Priority:** `BLOCK \u003e ASK \u003e ALLOW \u003e SKIP`\n\n| Decision  | Effect                      |\n| :-------: | --------------------------- |\n| **deny**  | Command blocked with reason |\n|  **ask**  | User prompted for approval  |\n| **allow** | Auto-approved               |\n\n\u003e Unknown commands always require approval.\n\n### Settings.json Integration\n\nbash-gates reads your Claude Code settings from `~/.claude/settings.json` and `.claude/settings.json` (project) to respect your explicit permission rules:\n\n| settings.json | bash-gates | Result                                       |\n| ------------- | ---------- | -------------------------------------------- |\n| `deny` rule   | (any)      | Defers to Claude Code (respects your deny)   |\n| `ask` rule    | (any)      | Defers to Claude Code (respects your ask)    |\n| `allow` rule  | dangerous  | **deny** (bash-gates still blocks dangerous) |\n| `allow`/none  | safe       | **allow**                                    |\n| none          | unknown    | **ask**                                      |\n\nThis ensures bash-gates won't accidentally bypass your explicit deny rules while still providing security against dangerous commands.\n\n**Settings file priority** (highest wins):\n\n| Priority    | Location                                 | Description                   |\n| ----------- | ---------------------------------------- | ----------------------------- |\n| 1 (highest) | `/etc/claude-code/managed-settings.json` | Enterprise managed            |\n| 2           | `.claude/settings.local.json`            | Local project (not committed) |\n| 3           | `.claude/settings.json`                  | Shared project (committed)    |\n| 4 (lowest)  | `~/.claude/settings.json`                | User settings                 |\n\n### Accept Edits Mode\n\nWhen Claude Code is in `acceptEdits` mode, bash-gates auto-allows file-editing commands:\n\n```bash\n# In acceptEdits mode - auto-allowed\nsd 'old' 'new' file.txt           # Text replacement\nprettier --write src/             # Code formatting\nast-grep -p 'old' -r 'new' -U .   # Code refactoring\nsed -i 's/foo/bar/g' file.txt     # In-place sed\nblack src/                        # Python formatting\neslint --fix src/                 # Linting with fix\n```\n\n**Still requires approval (even in acceptEdits):**\n\n- Package managers: `npm install`, `cargo add`\n- Git operations: `git push`, `git commit`\n- Deletions: `rm`, `mv`\n- Blocked commands: `rm -rf /` still denied\n\n### Modern CLI Hints\n\n_Requires Claude Code 1.0.20+_\n\nWhen Claude uses legacy commands, bash-gates suggests modern alternatives via `additionalContext`. This helps Claude learn better patterns over time without modifying the command.\n\n```bash\n# Claude runs: cat README.md\n# bash-gates returns:\n{\n  \"hookSpecificOutput\": {\n    \"permissionDecision\": \"allow\",\n    \"additionalContext\": \"Tip: Use 'bat README.md' for syntax highlighting and line numbers (Markdown rendering)\"\n  }\n}\n```\n\n| Legacy Command                | Modern Alternative | When triggered                       |\n| ----------------------------- | ------------------ | ------------------------------------ |\n| `cat`, `head`, `tail`, `less` | `bat`              | Always (`tail -f` excluded)          |\n| `grep` (code patterns)        | `sg`               | AST-aware code search                |\n| `grep` (text/log/config)      | `rg`               | Any grep usage                       |\n| `find`                        | `fd`               | Always                               |\n| `ls`                          | `eza`              | With `-l` or `-a` flags              |\n| `sed`                         | `sd`               | Substitution patterns (`s/.../.../`) |\n| `awk`                         | `choose`           | Field extraction (`print $`)         |\n| `du`                          | `dust`             | Always                               |\n| `ps`                          | `procs`            | With `aux`, `-e`, `-A` flags         |\n| `curl`, `wget`                | `xh`               | JSON APIs or verbose mode            |\n| `diff`                        | `delta`            | Two-file comparisons                 |\n| `xxd`, `hexdump`              | `hexyl`            | Always                               |\n| `cloc`                        | `tokei`            | Always                               |\n| `tree`                        | `eza -T`           | Always                               |\n| `man`                         | `tldr`             | Always                               |\n| `wc -l`                       | `rg -c`            | Line counting                        |\n\n**Only suggests installed tools.** Hints are cached (7-day TTL) to avoid repeated `which` calls.\n\n```bash\n# Refresh tool detection cache\nbash-gates --refresh-tools\n\n# Check which tools are detected\nbash-gates --tools-status\n```\n\n### Approval Learning\n\nWhen you approve commands (via Claude Code's permission prompt), bash-gates tracks them and lets you permanently save patterns to settings.json.\n\n```bash\n# After approving some commands, review pending approvals\nbash-gates pending list\n\n# Interactive TUI dashboard\nbash-gates review          # current project only\nbash-gates review --all    # all projects\n\n# Or approve directly via CLI\nbash-gates approve 'npm install*' -s local\nbash-gates approve 'cargo*' -s user\n\n# Manage existing rules\nbash-gates rules list\nbash-gates rules remove 'pattern' -s local\n```\n\n**Scopes:**\n| Scope | File | Use case |\n|-------|------|----------|\n| `local` | `.claude/settings.local.json` | Personal project overrides (not committed) |\n| `user` | `~/.claude/settings.json` | Global personal use |\n| `project` | `.claude/settings.json` | Share with team |\n\n**Review TUI** (`bash-gates review`):\n\nThree-panel dashboard -- project sidebar, command list, and detail panel.\n\n- **Sidebar**: Lists projects with pending counts, auto-selects current project. Click or arrow to switch.\n- **Command list**: Full commands with color-coded segments (green=allowed, yellow=ask, red=blocked). Multi-select with Space for batch operations.\n- **Detail panel**: Shows segment breakdown, pattern (cycle with Left/Right), scope (cycle with Left/Right), and action buttons.\n\nCompound commands (`\u0026\u0026`, `||`, `|`) show per-segment patterns so you can approve individual parts.\n\n| Key | Action |\n| --- | ------ |\n| `Tab` | Cycle panel focus (Sidebar -\u003e Commands -\u003e Detail) |\n| `Up`/`Down` or `j`/`k` | Navigate within focused panel |\n| `Left`/`Right` or `h`/`l` | Cycle pattern or scope (in detail panel) |\n| `Space` | Toggle multi-select on command |\n| `Enter` | Approve selected command(s) |\n| `d` | Skip (remove from pending) |\n| `D` | Deny (add to settings.json deny list) |\n| `q` or `Esc` | Quit |\n\n---\n\n## Installation\n\n### Download Binary\n\n```bash\n# Linux x64\ncurl -Lo ~/.local/bin/bash-gates \\\n  https://github.com/camjac251/bash-gates/releases/latest/download/bash-gates-linux-amd64\nchmod +x ~/.local/bin/bash-gates\n\n# Linux ARM64\ncurl -Lo ~/.local/bin/bash-gates \\\n  https://github.com/camjac251/bash-gates/releases/latest/download/bash-gates-linux-arm64\nchmod +x ~/.local/bin/bash-gates\n\n# macOS Apple Silicon\ncurl -Lo ~/.local/bin/bash-gates \\\n  https://github.com/camjac251/bash-gates/releases/latest/download/bash-gates-darwin-arm64\nchmod +x ~/.local/bin/bash-gates\n\n# macOS Intel\ncurl -Lo ~/.local/bin/bash-gates \\\n  https://github.com/camjac251/bash-gates/releases/latest/download/bash-gates-darwin-amd64\nchmod +x ~/.local/bin/bash-gates\n```\n\n### Build from Source\n\n```bash\n# Requires Rust 1.85+\ncargo build --release\n# Binary: ./target/x86_64-unknown-linux-musl/release/bash-gates\n```\n\n### Configure Claude Code\n\nUse the `hooks` subcommand to configure Claude Code:\n\n```bash\n# Install to user settings (recommended)\nbash-gates hooks add -s user\n\n# Install to project settings (shared with team)\nbash-gates hooks add -s project\n\n# Install to local project settings (not committed)\nbash-gates hooks add -s local\n\n# Preview changes without writing\nbash-gates hooks add -s user --dry-run\n\n# Check installation status\nbash-gates hooks status\n\n# Output hooks JSON for manual config\nbash-gates hooks json\n```\n\n**Scopes:**\n| Scope | File | Use case |\n|-------|------|----------|\n| `user` | `~/.claude/settings.json` | Personal use (recommended) |\n| `project` | `.claude/settings.json` | Share with team |\n| `local` | `.claude/settings.local.json` | Personal project overrides |\n\n**All three hooks are installed:**\n\n- `PreToolUse` - Gates commands for main session, tracks \"ask\" decisions\n- `PermissionRequest` - Gates commands for subagents (where PreToolUse's allow is ignored)\n- `PostToolUse` - Detects successful execution, queues for permanent approval\n\n\u003cdetails\u003e\n\u003csummary\u003eManual installation\u003c/summary\u003e\n\nAdd to `~/.claude/settings.json`:\n\n```json\n{\n  \"hooks\": {\n    \"PreToolUse\": [\n      {\n        \"matcher\": \"Bash\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"~/.local/bin/bash-gates\",\n            \"timeout\": 10\n          }\n        ]\n      }\n    ],\n    \"PermissionRequest\": [\n      {\n        \"matcher\": \"Bash\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"~/.local/bin/bash-gates\",\n            \"timeout\": 10\n          }\n        ]\n      }\n    ],\n    \"PostToolUse\": [\n      {\n        \"matcher\": \"Bash\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"~/.local/bin/bash-gates\",\n            \"timeout\": 10\n          }\n        ]\n      }\n    ]\n  }\n}\n```\n\n\u003c/details\u003e\n\n### Claude Code Plugin (Optional)\n\nbash-gates ships as a [Claude Code plugin](https://code.claude.com/docs/en/plugins) with the `/bash-gates:review` skill for interactive approval management. The plugin provides the skill only -- hook installation is handled by the binary (see [Configure Claude Code](#configure-claude-code) above).\n\n**Prerequisites:** The `bash-gates` binary must be installed and hooks configured before using the plugin.\n\n**Install from marketplace:**\n\n```bash\n# In Claude Code, add the marketplace\n/plugin marketplace add camjac251/bash-gates\n\n# Install the plugin\n/plugin install bash-gates@camjac251-bash-gates\n```\n\n**Install from local clone:**\n\n```bash\n# Launch Claude Code with the plugin loaded\nclaude --plugin-dir /path/to/bash-gates\n```\n\n**Using the review skill:**\n\n```bash\n# Review all pending approvals\n/bash-gates:review\n\n# Review only current project\n/bash-gates:review --project\n```\n\nThe skill lists commands you've been manually approving, shows counts and suggested patterns, and lets you multi-select which to make permanent at your chosen scope (local, project, or user).\n\n| Step                   | What happens                                | Permission                 |\n| ---------------------- | ------------------------------------------- | -------------------------- |\n| List pending approvals | `bash-gates pending list`                   | Auto-approved (read-only)  |\n| Show current rules     | `bash-gates rules list`                     | Auto-approved (read-only)  |\n| Approve a pattern      | `bash-gates approve '\u003cpattern\u003e' -s \u003cscope\u003e` | Requires your confirmation |\n\n---\n\n## Permission Gates\n\n### Bash Gates (Self)\n\nbash-gates recognizes its own CLI commands:\n\n| Allow                                                                                                                   | Ask                                                                                  |\n| ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |\n| `pending list`, `pending count`, `rules list`, `hooks status`, `--help`, `--version`, `--tools-status`, `--export-toml` | `approve`, `rules remove`, `pending clear`, `hooks add`, `review`, `--refresh-tools` |\n\n### Basics\n\n~130+ safe read-only commands: `echo`, `cat`, `ls`, `grep`, `rg`, `awk`, `sed` (no -i), `ps`, `whoami`, `date`, `jq`, `yq`, `bat`, `fd`, `tokei`, `hexdump`, and more. Custom handlers for `xargs` (safe only with known-safe targets) and `bash -c`/`sh -c` (parses inner script).\n\n### Beads Issue Tracker\n\n[Beads](https://github.com/steveyegge/beads) - Git-native issue tracking\n\n| Allow                                                                                | Ask                                                                              |\n| ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- |\n| `list`, `show`, `ready`, `blocked`, `search`, `stats`, `doctor`, `dep tree`, `prime` | `create`, `update`, `close`, `delete`, `sync`, `init`, `dep add`, `comments add` |\n\n### MCP CLI\n\n`mcp-cli` - Claude Code's [experimental token-efficient MCP interface](https://github.com/anthropics/claude-code/issues/12836#issuecomment-3629052941)\n\nInstead of loading full MCP tool definitions into the system prompt, Claude discovers tools on-demand via `mcp-cli` and executes them through Bash. Enable with `ENABLE_EXPERIMENTAL_MCP_CLI=true`.\n\n| Allow                                                           | Ask                        |\n| --------------------------------------------------------------- | -------------------------- |\n| `servers`, `tools`, `info`, `grep`, `resources`, `read`, `help` | `call` (invokes MCP tools) |\n\nPre-approve trusted servers in settings.json to avoid repeated prompts:\n\n```json\n{\n  \"permissions\": {\n    \"allow\": [\"mcp__perplexity\", \"mcp__context7__*\"],\n    \"deny\": [\"mcp__firecrawl__firecrawl_crawl\"]\n  }\n}\n```\n\nPatterns: `mcp__\u003cserver\u003e` (entire server), `mcp__\u003cserver\u003e__\u003ctool\u003e` (specific tool), `mcp__\u003cserver\u003e__*` (wildcard)\n\n### GitHub CLI\n\n| Allow                                                       | Ask                                                  | Block                        |\n| ----------------------------------------------------------- | ---------------------------------------------------- | ---------------------------- |\n| `pr list`, `issue view`, `repo view`, `search`, `api` (GET) | `pr create`, `pr merge`, `issue create`, `repo fork` | `repo delete`, `auth logout` |\n\n### Git\n\n| Allow                                        | Ask                                      | Ask (warning)                               |\n| -------------------------------------------- | ---------------------------------------- | ------------------------------------------- |\n| `status`, `log`, `diff`, `show`, `branch -a` | `add`, `commit`, `push`, `pull`, `merge` | `push --force`, `reset --hard`, `clean -fd` |\n\n### Shortcut CLI\n\n[shortcut-cli](https://github.com/shortcut-cli/shortcut-cli) - Community CLI for Shortcut\n\n| Allow                                                                                 | Ask                                                                                        |\n| ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |\n| `search`, `find`, `story` (view), `members`, `epics`, `workflows`, `projects`, `help` | `create`, `install`, `story` (with update flags), `search --save`, `api` (POST/PUT/DELETE) |\n\n### Cloud CLIs\n\nAWS, gcloud, terraform, kubectl, docker, podman, az, helm, pulumi\n\n| Allow                                         | Ask                                        | Block                                      |\n| --------------------------------------------- | ------------------------------------------ | ------------------------------------------ |\n| `describe-*`, `list-*`, `get`, `show`, `plan` | `create`, `delete`, `apply`, `run`, `exec` | `iam delete-user`, `delete ns kube-system` |\n\n### Network\n\n| Allow                         | Ask                                    | Block                   |\n| ----------------------------- | -------------------------------------- | ----------------------- |\n| `curl` (GET), `wget --spider` | `curl -X POST`, `wget`, `ssh`, `rsync` | `nc -e` (reverse shell) |\n\n### Filesystem\n\n| Allow                 | Ask                                 | Block                  |\n| --------------------- | ----------------------------------- | ---------------------- |\n| `tar -tf`, `unzip -l` | `rm`, `mv`, `cp`, `chmod`, `sed -i` | `rm -rf /`, `rm -rf ~` |\n\n### Developer Tools\n\n~50+ tools with write-flag detection: `jq`, `shellcheck`, `hadolint`, `vite`, `vitest`, `jest`, `tsc`, `esbuild`, `turbo`, `nx`\n\n| Safe by default                                                                                                         | Ask with flags                                          |\n| ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |\n| `ast-grep`, `yq`, `semgrep`, `sad`, `prettier`, `eslint`, `biome`, `ruff`, `black`, `gofmt`, `rustfmt`, `golangci-lint` | `-U`, `-i`, `--fix`, `--write`, `--commit`, `--autofix` |\n| `sd` (pipe mode safe, ask with file args), always ask: `watchexec` (runs commands), `dos2unix`                          |                                                         |\n\n### Package Managers\n\nnpm, pnpm, yarn, pip, uv, cargo, go, bun, conda, poetry, pipx, mise\n\n| Allow                                  | Ask                                          |\n| -------------------------------------- | -------------------------------------------- |\n| `list`, `show`, `test`, `build`, `dev` | `install`, `add`, `remove`, `publish`, `run` |\n\n### System\n\n**Database CLIs:** psql, mysql, sqlite3, mongosh, redis-cli\n**Build tools:** make, cmake, ninja, just, gradle, maven, bazel\n**OS Package managers:** apt, brew, pacman, nix, dnf, zypper, flatpak, snap\n**Other:** sudo, systemctl, crontab, kill\n\n| Allow                                           | Ask                               | Block                                                             |\n| ----------------------------------------------- | --------------------------------- | ----------------------------------------------------------------- |\n| `psql -l`, `make test`, `sudo -l`, `apt search` | `make deploy`, `sudo apt install` | `shutdown`, `reboot`, `mkfs`, `dd`, `fdisk`, `iptables`, `passwd` |\n\n---\n\n## Security Features\n\n### Pre-AST Security Checks\n\nComments are stripped before checking (quote-aware, respects bash word-boundary rules for `#`) so patterns inside comments don't trigger false positives.\n\n```bash\ncurl https://example.com | bash     # ask - pipe to shell\neval \"rm -rf /\"                     # ask - arbitrary execution\nsource ~/.bashrc                    # ask - sourcing script\necho $(rm -rf /tmp/*)               # ask - dangerous substitution\nfind . | xargs rm                   # ask - xargs to rm\necho \"data\" \u003e /etc/passwd           # ask - output redirection\n```\n\n### Compound Command Handling\n\nStrictest decision wins:\n\n```bash\ngit status \u0026\u0026 rm -rf /     # deny  (rm -rf / blocked)\ngit status \u0026\u0026 npm install  # ask   (npm install needs approval)\ngit status \u0026\u0026 git log      # allow (both read-only)\n```\n\n### Smart sudo Handling\n\n```bash\nsudo apt install vim          # ask - \"sudo: Installing packages (apt)\"\nsudo systemctl restart nginx  # ask - \"sudo: systemctl restart\"\n```\n\n---\n\n## Testing\n\n```bash\ncargo test                        # Full suite\ncargo test gates::git             # Specific gate\ncargo test -- --nocapture         # With output\n```\n\n### Manual Testing\n\n```bash\n# Allow\necho '{\"tool_name\":\"Bash\",\"tool_input\":{\"command\":\"git status\"}}' | bash-gates\n# -\u003e {\"hookSpecificOutput\":{\"permissionDecision\":\"allow\"}}\n\n# Ask\necho '{\"tool_name\":\"Bash\",\"tool_input\":{\"command\":\"npm install\"}}' | bash-gates\n# -\u003e {\"hookSpecificOutput\":{\"permissionDecision\":\"ask\",\"permissionDecisionReason\":\"npm: Installing packages\"}}\n\n# Deny\necho '{\"tool_name\":\"Bash\",\"tool_input\":{\"command\":\"rm -rf /\"}}' | bash-gates\n# -\u003e {\"hookSpecificOutput\":{\"permissionDecision\":\"deny\"}}\n```\n\n---\n\n## Architecture\n\n```\nsrc/\n├── main.rs              # Entry point, CLI commands\n├── models.rs            # Types (HookInput, HookOutput, Decision)\n├── parser.rs            # tree-sitter-bash AST parsing\n├── router.rs            # Security checks + gate routing\n├── settings.rs          # settings.json parsing and pattern matching\n├── hints.rs             # Modern CLI hints (cat→bat, grep→rg, etc.)\n├── tool_cache.rs        # Tool availability cache for hints\n├── mise.rs              # Mise task file parsing and command extraction\n├── package_json.rs      # package.json script parsing and command extraction\n├── tracking.rs          # PreToolUse→PostToolUse correlation (15min TTL)\n├── pending.rs           # Pending approval queue (JSONL format)\n├── patterns.rs          # Pattern suggestion algorithm\n├── post_tool_use.rs     # PostToolUse handler\n├── permission_request.rs # PermissionRequest hook handler\n├── settings_writer.rs   # Write rules to Claude settings files\n├── toml_export.rs       # TOML policy export for Gemini CLI\n├── generated/           # Auto-generated by build.rs (DO NOT EDIT)\n│   ├── rules.rs         # Rust gate functions from rules/*.toml\n│   └── toml_policy.rs   # Gemini CLI TOML policy string\n├── tui/                 # Interactive review TUI (three-panel dashboard)\n└── gates/               # 13 specialized permission gates\n    ├── mod.rs           # Gate registry (ordered by priority)\n    ├── helpers.rs       # Common gate helper functions\n    ├── bash_gates.rs    # bash-gates CLI itself\n    ├── basics.rs        # Safe commands (~130+)\n    ├── beads.rs         # Beads issue tracker (bd) - github.com/steveyegge/beads\n    ├── mcp.rs           # MCP CLI (mcp-cli) - Model Context Protocol\n    ├── gh.rs            # GitHub CLI\n    ├── git.rs           # Git\n    ├── shortcut.rs      # Shortcut CLI (short) - github.com/shortcut-cli/shortcut-cli\n    ├── cloud.rs         # AWS, gcloud, terraform, kubectl, docker, podman, az, helm, pulumi\n    ├── network.rs       # curl, wget, ssh, rsync, netcat, HTTPie\n    ├── filesystem.rs    # rm, mv, cp, chmod, tar, zip\n    ├── devtools.rs      # sd, ast-grep, yq, semgrep, biome, prettier, eslint, ruff, black\n    ├── package_managers.rs  # npm, pnpm, yarn, pip, uv, cargo, go, bun, conda, poetry, pipx, mise\n    └── system.rs        # psql, mysql, make, sudo, systemctl, OS pkg managers, build tools\n```\n\n---\n\n## Gemini CLI Integration\n\nGemini CLI's hook system cannot prompt users (only allow/block). Use the policy engine instead:\n\n```bash\nbash-gates --export-toml \u003e ~/.gemini/policies/bash-gates.toml\n```\n\nThis exports 700+ policy rules derived from the gate definitions:\n\n| Priority | Action     | Examples                              |\n| -------- | ---------- | ------------------------------------- |\n| 900+     | `deny`     | `rm -rf /`, `gh repo delete`          |\n| 200-299  | `ask_user` | `npm install`, `git push`             |\n| 100-199  | `allow`    | `git status`, `ls`, `cat`             |\n| 1        | `ask_user` | Default fallback for unknown commands |\n\n---\n\n## Links\n\n- [Claude Code Hooks Documentation](https://code.claude.com/docs/en/hooks)\n- [Claude Code MCP-CLI (experimental)](https://github.com/anthropics/claude-code/issues/12836#issuecomment-3629052941)\n- [tree-sitter-bash](https://github.com/tree-sitter/tree-sitter-bash)\n- [Beads Issue Tracker](https://github.com/steveyegge/beads)\n- [Shortcut CLI](https://github.com/shortcut-cli/shortcut-cli)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcamjac251%2Fbash-gates","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcamjac251%2Fbash-gates","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcamjac251%2Fbash-gates/lists"}