Skip to content

Repository files navigation

Gatekeeper

One terminal to rule all your Claude Code sessions.

When you run multiple Claude Code sessions across terminals or IDE windows, each one asks for permission in its own terminal. Gatekeeper intercepts every request and routes them to a single dashboard — you approve, deny, or auto-approve without switching windows.

PythonPlatformLicenseGitHub Stars


What it looks like

Gatekeeper demo

Left pane — all active Claude sessions with status badges ([auto] = auto-approve enabled)
Middle pane — pending permission requests with age timer
Right pane — full request detail, danger warnings, and a numbered approval menu


Features

  • Unified approval terminal — all Claude sessions route here regardless of where they run
  • Claude Code-style numbered menu1 allow once, 2 always allow (saves rule), 3 deny; / to move cursor, Enter to confirm
  • Persistent allow (option 2) — saves a rule to Gatekeeper config so the command skips the queue next time
  • Sessions shown immediately — reads ~/.claude/sessions/ on startup, no waiting for a hook call
  • Auto-approve per session — mark trusted sessions to silently pass routine tool calls
  • Hard safety rulesrm, ssh, sudo, --force, SQL mutations, writes to /etc/ always require manual approval, even on auto sessions
  • Sole permission gatebypassPermissions mode disables Claude Code's own dialogs; Gatekeeper is the only checkpoint
  • Message injection — type a message in Gatekeeper and it appears in the target Claude terminal as keyboard input
  • Window linking — link each session to its terminal tab so messages go to exactly the right window
  • Daily logs + stats — every decision is recorded; gatekeeper stats shows rates by day and session
  • Terminal fallback — if Gatekeeper is not running, a Y/n prompt appears in the Claude terminal so nothing hangs

Requirements

  • Linux with X11 (echo $DISPLAY should show :0 or similar)
  • Python 3.11+
  • Claude Code CLI
  • Any X11 terminal emulator (gnome-terminal, Kitty, Alacritty, etc.)

Installation

git clone https://github.com/Btocode/gatekeeper
cd gatekeeper
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
bash install.sh

install.sh does four things:

  1. Installs wrapper scripts in ~/.claude/bin/
  2. Registers a PreToolUse hook in ~/.claude/settings.json — Claude Code calls this before every tool use
  3. Adds blanket permissions.allow rules (Bash(**), Read(**), Write(**), Edit(**), …) using ** to match path separators
  4. Sets permissions.defaultMode = "bypassPermissions" — disables Claude Code's built-in permission dialogs entirely so Gatekeeper is the sole approval gate (Claude Code's hardcoded sensitive-path prompts for /proc/, /sys/, ~/.bashrc, etc. only suppress in this mode)

Usage

Open a dedicated terminal and run:

gatekeeper

Start your Claude Code sessions anywhere — other terminals, VS Code, JetBrains, anywhere. Every Bash, Edit, Write, or Agent call will appear in Gatekeeper.

Approving from the Claude terminal instead of Gatekeeper

By default the hook waits up to 5 minutes for Gatekeeper to respond, then falls back to a Y/n prompt directly in the Claude terminal. This means:

SituationWhat happens
Gatekeeper runningRequest appears in dashboard — approve with A / D
Gatekeeper not running[Permission required] Y/n prompt appears in Claude terminal
Gatekeeper running, no response in 5 minHook times out, falls back to Y/n in Claude terminal

To approve from the Claude terminal immediately (skip Gatekeeper for a session):

# Set timeout to 0 — always use terminal prompt, ignore daemon
GATEKEEPER_TIMEOUT=0 claude
# Or set a short timeout (e.g. 10 seconds)
GATEKEEPER_TIMEOUT=10 claude

To permanently prefer terminal prompts, add to ~/.zshrc:

export GATEKEEPER_TIMEOUT=0

To stop Gatekeeper entirely, press Q in the dashboard — subsequent hook calls fall back to the terminal prompt automatically.


Keyboard shortcuts

KeyPaneAction
TabanySwitch focus between Sessions and Queue
j / kanyNavigate queue items or sessions
/ QueueMove the approval cursor (1 / 2 / 3)
1QueueYes — allow this request
2QueueYes, for this session only — allows without saving permanently
3QueueNo — deny this request
EnterQueueConfirm highlighted option
AQueueYes — allow (shortcut)
DQueueNo — deny (shortcut)
ASessionsToggle auto-approve for the selected session
ManySend a message to the selected session
LSessionsLink the session to a terminal window
USessionsUnlink the session from its terminal window
SanyOpen settings (tool types, bash categories, custom patterns)
QanyQuit

Auto-approve

Mark a session (A in the Sessions pane) to silently allow all its tool calls. The session shows [auto] — you only see requests that need your attention.

What auto-approve never skips

No matter what, these always require manual approval:

CategoryWhat's blocked
File deletionrm, rmdir, shred
Remote accessssh, scp, rsync, sftp
Privilege escalationsudo, su
Service controlsystemctl stop/disable, service stop
Containersdocker rm/kill/prune, kubectl delete
Infrastructureterraform apply/destroy
Destructive gitpush --force, reset --hard, clean -f
Sensitive pathsWrites to /etc/, /usr/, ~/.ssh/, ~/.aws/
Disk opsdd, mkfs, fdisk

Read-only commands — grep, find, ls, cat, git status, npm install, SELECT queries — always pass through auto-approve freely.


Session linking

Linking maps a Claude session to its terminal window so the M (message) key knows exactly where to send input.

  1. Tab to the Sessions pane, navigate to a session
  2. Press L — an overlay appears
  3. Switch to the Claude terminal tab (alt+tab, click, etc.)
  4. Gatekeeper detects the focus change and links automatically — session shows [linked]

Links persist in ~/.claude/perm-window-map.json.


Sending messages

Press M, type your message, press Enter. Gatekeeper injects the text into the linked Claude terminal using X11 XTEST — it appears and submits automatically, exactly as if you typed it and pressed Enter there. No need to switch to that terminal.

Useful for:

  • Answering Claude's mid-task questions (A / B / C?) without switching windows
  • Explaining why you denied a request
  • Redirecting Claude to a different approach while it waits

Requires the session to be linked first (L key).

Tabs vs windows

Message injection works when each Claude session runs in its own terminal window. If multiple sessions share one window as tabs, all tabs have the same X11 window ID — Gatekeeper cannot distinguish between them.

SetupMessage injection
Each session in its own window✅ Works
Sessions as tabs in one window❌ Cannot target specific tab

Workaround: open each Claude session in a new terminal window instead of a new tab (kitty, gnome-terminal --window, etc.).


Stats

gatekeeper stats # today
gatekeeper stats 7 # last 7 days
gatekeeper stats all # all time
====================================================
GATEKEEPER STATS
====================================================
Total decisions : 177
Auto-approved : 16 ( 9%)
Manual reviewed : 161 ( 90%)
allowed : 161
denied : 0
Auto-approved by session:
b73f7ccc 7 calls
a8ed1d57 5 calls
Auto-approved by tool:
Bash 11
Edit 5
====================================================

Logs live in ~/.claude/perm-logs/YYYY-MM-DD.log, one file per day, kept indefinitely.


How it works

 Claude session A Claude session B Claude session C
(any terminal/IDE) (any terminal/IDE) (any terminal/IDE)
│ │ │
PreToolUse hook PreToolUse hook PreToolUse hook
(blocks Claude) (blocks Claude) (blocks Claude)
└────────────────────────┼────────────────────────┘
│ Unix socket
▼
┌────── Gatekeeper daemon ──────┐
│ blessed TUI │
│ asyncio socket server │
│ session registry │
└───────────────────────────────┘
(your terminal)

A PreToolUse hook fires before every tool call in every Claude session. It connects to Gatekeeper's Unix socket at /tmp/claude-perm-$USER.sock, sends the request, and waits. Gatekeeper shows the request in the UI. When you press A or D, the decision travels back through the socket — Claude proceeds or stops.

Sessions are discovered at startup by reading ~/.claude/sessions/*.json (the same files used by claude /resume), so all running sessions appear immediately.

If Gatekeeper is not running, the hook falls back to a Y/n prompt in the Claude terminal — nothing hangs.


Files

PathPurpose
~/.claude/bin/gatekeeperGatekeeper daemon
~/.claude/bin/gatekeeper-hookHook called by Claude Code
~/.claude/bin/gatekeeper-statsStats backend (gatekeeper stats)
~/.claude/perm-logs/YYYY-MM-DD.logDaily decision logs
~/.claude/perm-window-map.jsonSession → window links
~/.claude/perm-auto-approve.jsonAuto-approve session list

Uninstall

gatekeeper uninstall

Removes the hook, blanket allow rules, and wrapper scripts. Claude Code's own permission dialogs are restored automatically.


License

MIT

About

Terminal dashboard that aggregates Claude Code permission prompts from all sessions into one place

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages