I built MMI (Mother May I?) with Claude Code to solve an annoying friction point: manually approving every single Bash command.
The Problem
Claude Code asks for permission before running any shell command. This is sensible from a security standpoint, but it means you're constantly hitting "approve" for commands like git status, pytest, or ls -la. It breaks flow and adds friction to every development session.
The Solution
MMI is a CLI hook that auto-approves known-safe commands while maintaining a fail-secure default. Unrecognized commands still require manual approval.
How it works:
1. Deny list checked first – Dangerous patterns (sudo, rm -rf /, chmod 777) are always rejected
2. Safe commands allowlisted – Read-only commands, test runners, linters, and build tools you configure
3. Proper shell parsing – Uses an AST-based parser (mvdan.cc/sh) to correctly handle pipes, chains, and quoted strings
4. Audit trail – Every decision logged to JSON-lines for debugging and compliance
Key design decisions:
- Fail-secure: Unknown commands require manual approval
- Command chains validated: "safe && dangerous" is rejected (ALL segments must be safe)
- Wrapper-aware: Strips timeout, env, .venv/bin/ before validation
- Heredoc-smart: Backticks inside quoted heredocs treated as literal text
Example config (TOML):
``` [safe] simple = ["ls", "pwd", "cat", "head", "tail"] subcommands.git = ["status", "log", "diff", "add", "commit", "push"] subcommands.cargo = ["build", "test", "check", "clippy"]
[deny]
simple = ["sudo", "su", "doas"]
regex = ["rm\\s+(-[^\\s]*)?.*\\s+/($|\\s)"]
```A note on security
Claude Code recently added built-in sandbox mode that restricts file system writes and network access. This is a great step toward secure defaults. However, MMI still provides value even with sandboxing:
- Audit trail – Every command decision logged for review and compliance
- Explicit allowlists – Know exactly what's approved rather than relying on implicit sandbox rules
- Deny patterns – Block specific dangerous patterns before they hit the sandbox
- Reduced interruptions – Sandbox mode can still prompt; MMI auto-approves known-safe commands
No allowlist can anticipate every attack vector. MMI is a convenience layer that reduces friction for common safe commands while maintaining defense-in-depth – it works alongside sandboxing, not as a replacement.
Why not just approve everything?
That defeats the purpose of Claude Code's permission system. MMI lets you define exactly which commands you trust, keeps a complete audit trail, and defaults to asking when uncertain.
The repo includes example configs for Python, Node, Rust, and a strict read-only mode.
GitHub: https://github.com/dgerlanc/mmi
Blog post with more details: https://dangerlanc.com/writing/mmi/