Because ls shouldn't need approval
🍴 Fork Enhancements (vs upstream)
- File Edit/Read Approval —
allow-edit/read,ask-edit/read,deny-edit/readrules - Include directive —
include <path-or-glob>for composable config files - Exclusive config —
DIPPY_CONFIG_ONLYand--config-onlyisolate role-specific processes from user and project configuration - Context-aware rules —
[flags]syntax with@subshell,@compound, negation (!) - Scoped handler delegation —
delegate [flags] command *sends a matched command through its native safety handler instead of approving it outright, including per-target SSH context - Environment context flags —
set context-env VARexposes an environment variable as the flag[$VAR=value], so one config can hold per-agent rules across commands, file edit/read operations, and web requests - Custom wrappers —
wrapper <name>for project-specific tools (ssh, docker exec, etc.), including literal quoted-heredoc script analysis with--script-stdin - Option rules —
allow-opt,ask-opt,deny-optfor subcommand/flag control - WebSearch support — auto-approval for WebSearch tool (by tony)
- Tk Approval Provider (
dippy-askpass-gui) — standalone Tk GUI approval dialog with operation classification (Read File, Edit File, Command, Web Request, MCP Tool), single-key keyboard shortcuts (y/Y/Enter= allow,n/N/Esc= deny), and multi-monitor geometric centering viaxrandr - Gemini CLI support — integrated hook support for Gemini CLI tools
- Pure Dippy Control (Gemini & AGY) — YOLO mode automation via
dippy hooks setup-gemini-yoloand AGY--dangerously-skip-permissionsbinary enforcement with askpass GUI resolution - Antigravity CLI (AGY) support — native lifecycle hook integration for Antigravity CLI with named-hook format in
~/.gemini/config/hooks.jsonand.agents/hooks.json, plus multi-workspace session resolution (workspacePaths) - Codex CLI support — native
hooks.jsonintegration for CodexPreToolUse/PermissionRequest/PostToolUseonBash - Codex enforcement model —
allowauto-approves viaPermissionRequest;denyhard-blocks viaexit 2;askfalls back to Codex approval UI - Structured JSON output — for PostToolUse hooks (by tony)
- SSH/sudo handlers — remote context support for ssh and sudo commands
cp/mvthrough redirect rules — destinations (andmvsources, which get removed) are checked againstallow-redirect/ask-redirect/deny-redirect, sodeny-redirect **/.dippyalso stopsmv .dippy /tmp/saved- DuckDB writes through redirect rules — writes to the main database follow
allow-redirect, while writable attachments and external file operations still require approval - Log rotation —
set log-rotate-max-days Nfor automatic cleanup - Notifier (Sidekick) —
set notifier-command "CMD"for external notifications (mail check). Supports long-polling via--idlein stop hooks. Useset notifier-include "tool1, tool2"to limit when it triggers. - Idle Prompt Notifications —
set idle-notifier-command "notify-send {title} {message}"for notifications when Claude is waiting for input - Hook approvals log control —
set log-hook-approvals offto disable hook-approvals.log - Hybrid mode —
set default passto let Claude decide unmatched commands - Audit log —
cwd,agent, andsuggestionfields for better context - CLI mode — standalone command validation with
--cmd,--stdin,--json,--remote - Approved execution —
dippy runand allowlisteddippy run-on-servercommands classify a quoted argument or literal quoted-heredoc script before local, SSH, tmux, or Herdr execution; uncertain remote results stay blocked until recovery - Optional project SSH profiles — SSH, tmux and Herdr share explicit SSH config/agent selection with no user-authentication fallback, private control sockets, and project-scoped recovery; ordinary user SSH settings remain the default
- Multi-Agent Support — dedicated modes for Claude, Gemini, Antigravity CLI (AGY), pi-mono, Moltbot, Codex, Windsurf, PearAI
- pi-mono extension — TypeScript extension for pi-mono AI assistant
- Python
-cAST analysis —python -c 'code'is statically analyzed for safety instead of always requiring confirmation. Safe code (no I/O, no dangerous imports) is auto-approved (design by nickdaview) - Configurable Python modules —
python-allow-moduleandpython-deny-moduledirectives to customize which modules are safe or dangerous during-canalysis, pluspython-allow-symbol sys.stdinto allow a single name from a module that is otherwise too broad to trust (design by nickdaview) - CLI management —
dippy hooks install/uninstall/listanddippy doctordiagnostics
Stop the permission fatigue. Claude Code asks for approval on every
ls,git status, andcat- destroying your flow state. You check Slack, come back, and your assistant's just sitting there waiting.
Dippy is a shell command hook that auto-approves safe commands while still prompting for anything destructive. When it blocks, your custom deny messages can steer Claude back on track—no wasted turns. Get up to 40% faster development without disabling permissions entirely.
Built on Parable, our own hand-written bash parser—no external dependencies, just pure Python. 14,000+ tests between the two.
Example: rejecting unsafe operation in a chain
Example: rejecting a command with advice, so Claude can keep going
- Complex pipelines:
ps aux | grep python | awk '{print $2}' | head -10 - Chained reads:
git status && git log --oneline -5 && git diff --stat - Cloud inspection:
aws ec2 describe-instances --filters "Name=tag:Environment,Values=prod" - Container debugging:
docker logs --tail 100 api-server 2>&1 | grep ERROR - Safe redirects:
grep -r "TODO" src/ 2>/dev/null,ls &>/dev/null - Command substitution:
ls $(pwd),git diff foo-$(date).txt
- Subshell injection:
git $(echo rm) foo.txt,echo $(rm -rf /) - Subtle file writes:
curl https://example.com > script.sh,tee output.log - Hidden mutations:
git stash drop,npm unpublish,brew unlink - Cloud danger:
aws s3 rm s3://bucket --recursive,kubectl delete pod - Destructive chains:
rm -rf node_modules && npm install(blocks the whole thing)
Subagents ignore PreToolUse hook decisions - Claude Code subagents (spawned via Task tool) do not respect allow/deny decisions from PreToolUse hooks. Even when Dippy returns "permissionDecision": "allow", subagents will still prompt for approval.
- Cause: Known bug in Claude Code (#4740, #4669)
- Status: Closed as "not planned" by Anthropic (January 2026)
- Impact: Hooks work correctly in main sessions but are ignored in subagents
- Workaround: Use explicit config rules instead of relying on hook decisions
See docs/subagent-hook-issues.md for detailed analysis.
# Clone the repository
git clone https://github.com/orgoj/Dippy.git
cd Dippy
# Install via uv tool (recommended)
uv tool install .
# Verify installation
dippy --versionNote: Make sure ~/.local/bin is on your PATH.
uv pip install -e .The easiest way to configure Dippy is using the CLI commands:
# Install for Claude Code (global)
dippy hooks install claude --global
# Install for Gemini CLI (global)
dippy hooks install gemini --global
# Install for Cursor IDE (global)
dippy hooks install cursor --global
# Install for Windsurf (global)
dippy hooks install windsurf --global
# Install for Codex CLI (global, requires hooks feature flag)
dippy hooks install codex --global# Check hook status
dippy hooks list
# Run diagnostics
dippy doctorThat's it! Dippy is now configured and will auto-approve safe commands.
If you prefer manual configuration or need project-specific settings:
Claude Code - add to ~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash|Write|Edit|MultiEdit|Read|LS|Glob|Grep|Search|WebSearch|mcp__.*",
"hooks": [{ "type": "command", "command": "dippy" }]
}
],
"PostToolUse": [
{
"matcher": "Bash|WebSearch|mcp__.*",
"hooks": [{ "type": "command", "command": "dippy" }]
}
]
}
}Gemini CLI - add to ~/.gemini/settings.json:
{
"hooks": {
"BeforeTool": [
{
"matcher": "run_shell_command|write_file|replace|read_file|google_web_search",
"hooks": [{ "type": "command", "command": "dippy --gemini" }]
}
],
"AfterTool": [
{
"matcher": "run_shell_command|google_web_search",
"hooks": [{ "type": "command", "command": "dippy --gemini" }]
}
]
}
}Codex CLI - add to ~/.codex/hooks.json and enable hooks = true in ~/.codex/config.toml:
{
"hooks": {
"PreToolUse": [
{
"matcher": "^Bash$",
"hooks": [{ "type": "command", "command": "dippy --codex" }]
}
],
"PermissionRequest": [
{
"matcher": "^Bash$",
"hooks": [{ "type": "command", "command": "dippy --codex" }]
}
],
"PostToolUse": [
{
"matcher": "^Bash$",
"hooks": [{ "type": "command", "command": "dippy --codex" }]
}
]
}
}Current Codex behavior: Dippy auto-approves allowed shell commands in the
PermissionRequest hook, but Codex only emits that event when its own policy
already requires approval. PreToolUse cannot force a prompt: an ask there
is advisory and otherwise fails open. For an external wrapper that can change
state outside the sandbox, add a Codex execpolicy prompt rule so every wrapper
invocation reaches PermissionRequest:
prefix_rule(
pattern = ["cca-tmux-cli"],
decision = "prompt",
justification = "Let Dippy decide whether this remote command requires user approval.",
)Put global rules in ~/.codex/rules/*.rules or project rules in
.codex/rules/*.rules, then restart Codex. Prefer Dippy's own stable execution
surface for external commands: prompt dippy run and dippy run-on-server in
the agent policy, then let the inner Dippy invocation enforce the command rules.
See Codex CLI hooks.
Current Gemini behavior: Gemini CLI 0.42 treats BeforeTool hook allow as "continue to normal policy" by default. To enable Pure Dippy Control and avoid double prompts, use:
dippy hooks setup-gemini-yoloThis enables Gemini's native YOLO mode, trusting Dippy as the primary authority.
Codex sandbox gotcha: During Codex workspace-write tool execution on Linux, .codex can appear inside the sandbox as a synthetic read-only file-like path even when the host workspace does not contain a normal .codex file. That artifact comes from Codex sandbox path protection, not from Dippy.
Hooks installed:
- PreToolUse: Validates tools BEFORE execution (Bash, file ops, WebSearch, MCP)
- PostToolUse: Shows feedback messages AFTER execution (for
afterdirective)
Changing hook config requires restarting the agent session. For Codex, both hooks.json and config.toml are loaded at session start.
dippy run 'CMD'
dippy run-on-server SERVER 'CMD'
dippy run <<'DIPPY' # literal multiline local script
CMD
DIPPY
dippy run-on-server SERVER <<'DIPPY'
CMD
DIPPY
dippy recover SERVER # check an uncertain persistent run
dippy recover SERVER --clear # release after manual inspectionrun-on-server accepts only aliases declared with server SERVER. Its
transport comes from configuration and cannot be overridden at invocation.
By default it uses your ordinary SSH settings. Projects can opt into an
isolated SSH profile with their own
configuration, keys and authentication socket, shared by all three backends.
See the configuration reference for SSH,
tmux, Herdr, askpass, config-management setup, and the interaction between
approval and agent CLI timeouts. Projects with a supervising agent or a custom
user channel can set approval-wait-message without exposing the underlying
enforcement mechanism.
dippy hooks list # Show hook status for all agents
dippy hooks install <agent> # Install hooks (project-local)
dippy hooks install <agent> --global # Install hooks (global)
dippy hooks uninstall <agent> # Remove hooks (project-local)
dippy hooks uninstall <agent> --global # Remove hooks (global)Supported agents: claude, gemini, cursor, windsurf, codex
Status indicators:
+= installed?= legacy (olddippy-hookdetected)= not installed
Scopes:
- Project-local (default):
.claude/settings.json,.cursor/hooks.json,.gemini/settings.json,.codex/hooks.json - Global (
--global):~/.claude/settings.json,~/.cursor/hooks.json,~/.gemini/settings.json,~/.codex/hooks.json
dippy doctor # Run all health checks
dippy doctor --agent claude # Check specific agent
dippy doctor --verbose # Show detailed diagnosticsHealth checks:
- ✓ Installation (on PATH, version check)
- ✓ Hook status per agent (Claude, Gemini, Cursor, Windsurf, Codex, pi-mono)
- ✓ Codex
hooksfeature flag validation - ✓ Legacy hook detection with full path
- ✓ pi_wrapper check for pi-mono/moltbot
- ✓ Configuration validation (syntax errors)
- ✓ Log health (writable directories, file size warnings)
Exit codes: 0 (OK), 1 (warnings), 2 (critical issues)
Validate commands without running as a hook:
dippy --cmd 'rm -rf /' # validate a command
dippy --cmd 'ls -la' --json # JSON output
dippy --cmd 'git status' --cwd /path
echo 'ls -la' | dippy --stdin # read command from stdinOptions:
--cmd COMMAND— command to validate--stdin— read command from stdin--cwd PATH— working directory--json— output as JSON--config PATH— custom config file--config-only PATH— load only this config, skipping user and project config--agent NAME— force agent name in audit log--remote— skip local path checks--version— show version
Dippy adapts its output format and behavior based on the agent:
| Agent | Flag | Env Var | Hook Support |
|---|---|---|---|
| Claude Code | --claude |
DIPPY_CLAUDE=1 |
✅ |
| Gemini CLI | --gemini |
DIPPY_GEMINI=1 |
✅ |
| Cursor IDE | --cursor |
DIPPY_CURSOR=1 |
✅ preToolUse |
| Windsurf | --windsurf |
DIPPY_WINDSURF=1 |
✅ |
| pi-mono | --pi |
DIPPY_PI=1 |
extension |
| Moltbot | --moltbot |
DIPPY_MOLTBOT=1 |
extension |
| OpenAI Codex | --codex |
DIPPY_CODEX=1 |
✅ |
| PearAI | --pearai |
DIPPY_PEARAI=1 |
partial |
Each agent mode maintains its own approval log (e.g., ~/.claude/hook-approvals.log).
Dippy reads config from ~/.dippy/config (global) and .dippy (project).
# Allow safe commands
allow git status
allow ls *
allow cat *
# Block dangerous commands
deny rm -rf *
deny docker rm *
# Prompt with message
deny pip install "Use uv pip install instead"
deny python "Use uv run python"Auto-approve file operations using the same config:
allow-read src/**
allow-edit src/**
deny-read **/.env*
deny-edit **/.env*
ask-edit **/config.*# Include external config files
include ~/.dippy/shared-rules
include .dippy-local-*
# Log settings
set log ~/.dippy/audit.log
set log-full
set log-rotate-max-days 30
set log-hook-approvals off
# Default behavior
set default ask # prompt (default)
# set default pass # let Claude decide
# set default allow # auto-approve
# Context-aware rules
deny [!@subshell] cd * # deny cd outside subshell
allow [@subshell] cd * # allow (cd x && y)
# Custom wrappers
wrapper docker-exec
allow [docker-exec,prod] read *
# Option rules
allow-opt git status fetch log diff
deny-opt "git push" --force "Use --force-with-lease"
# MCP tools
allow-mcp mcp__github__get_*
deny-mcp mcp__*__delete_*
# After hook
after git commit * "Check project-tasks.md"Full documentation: docs/config.md
# Run diagnostics
dippy doctor
# Check hook status
dippy hooks list
# Reinstall hooks
dippy hooks uninstall claude --global
dippy hooks install claude --global- Claude Code:
~/.claude/hook-approvals.log - Gemini CLI:
~/.gemini/hook-approvals.log - Dippy audit:
~/.dippy/audit.log
- Hook not triggering → Run
dippy doctorto diagnose - JSON syntax errors → Check config with
dippy doctor - Legacy hook detected → Run
dippy hooks install <agent> --global
# Remove hooks
dippy hooks uninstall claude --global
dippy hooks uninstall gemini --global
# Uninstall tool
uv tool uninstall dippyDippy includes a TypeScript extension for pi-mono:
# Link the extension
ln -s /path/to/dippy/pi-extension/dippy-extension.ts \
~/.pi/agent/extensions/dippy-extension.tsUses your existing ~/.dippy/config and .dippy files.
# Install in development mode
uv pip install -e .
# Run tests
uv run python -m pytest
# Run specific test
uv run python -m pytest tests/test_agents.py -vFull documentation: docs/config.md Upstream repository: ldayton/Dippy




