# omamori
> **Pre-1.0** — Breaking changes may occur between minor versions.
AI Agent's Omamori — protect your system from dangerous commands executed via AI CLI tools.
### Supported AI CLI Tools
| **Claude Code** | `CLAUDECODE=1` | Verified |
| **Codex CLI** | `CODEX_CI=1` | Verified |
| **Cursor** | `CURSOR_AGENT=1` | Provisional |
| Any tool setting `AI_GUARD=1` | `AI_GUARD=1` | Fallback |
Detection requires exact `=1` value match. Tools that set these environment variables when executing shell commands are automatically detected.
## What It Does
When an AI CLI tool (Claude Code, Codex, Cursor, etc.) runs a shell command, omamori intercepts dangerous operations and replaces them with safe alternatives. **Terminal direct execution is not affected.**
```
[AI CLI Tool] → CLAUDECODE=1 → rm -rf target/
↓
[omamori shim]
↓
moved to Trash instead
```
```
[Terminal] → → rm -rf target/
↓
[/usr/bin/rm]
↓
deleted normally
```
## Quick Start
### Install via Homebrew (macOS)
```bash
brew install yottayoshida/tap/omamori
```
### Or build from source
```bash
cargo install --path .
```
### Setup
```bash
# 1. Install shims + hooks + config (all in one command)
omamori install --hooks
# 2. Add shim directory to PATH (add to .zshrc / .bashrc)
export PATH="$HOME/.omamori/shim:$PATH"
```
That's it. `install --hooks` auto-generates `config.toml`, runs verification, and shows a checklist:
```
omamori setup complete:
[done] Shims installed: rm, git, chmod
[done] Hook script generated
[done] Config created: ~/.config/omamori/config.toml
[done] All rules verified: 5 active, 6 detection tests passed
[todo] Add to your shell profile (~/.zshrc or ~/.bashrc):
export PATH="$HOME/.omamori/shim:$PATH"
```
## How It Works
**Layer 1 — PATH shim**: Symlinks for `rm`, `git`, `chmod` point to the omamori binary. When invoked, omamori checks for AI tool environment variables (e.g. `CLAUDECODE=1`) and applies rules only if an AI tool is detected.
**Layer 2 — Claude Code Hooks** (optional): A `PreToolUse` hook script catches bypass attempts like `/bin/rm` direct paths or `unset CLAUDECODE`.
## Default Rules
| `rm` | `-r`, `-rf`, `-fr`, `--recursive` | **trash** — move to macOS Trash |
| `git` | `reset --hard` | **stash-then-exec** — `git stash` first, then execute |
| `git` | `push --force`, `push -f` | **block** |
| `git` | `clean -fd`, `clean -fdx` | **block** |
| `chmod` | `777` | **block** |
Combined short flags are normalized: `rm -rfv` expands to match `-r` and `-rf` rules. The POSIX `--` separator is respected for target extraction.
## Configuration (v0.2+)
Built-in rules are always inherited. Config is auto-created by `install --hooks`. To regenerate manually:
```bash
omamori init # Creates ~/.config/omamori/config.toml (chmod 600)
omamori init --force # Overwrite existing config
omamori init --stdout # Print template to stdout (backward compat)
```
**Disable a rule** via CLI (v0.3+):
```bash
omamori config disable git-push-force-block
omamori config enable git-push-force-block # restore built-in default
omamori config list # show all rules with status
```
Or edit `config.toml` directly:
```toml
[[rules]]
name = "git-push-force-block"
enabled = false
```
**Move files to a custom directory** instead of Trash:
```toml
[[rules]]
name = "rm-to-backup"
command = "rm"
action = "move-to"
destination = "/tmp/omamori-quarantine/"
match_any = ["-r", "-rf", "-fr", "--recursive"]
message = "omamori moved targets to quarantine instead of deleting"
```
**Override an existing rule's action**:
```toml
[[rules]]
name = "rm-recursive-to-trash"
action = "move-to"
destination = "/tmp/omamori-quarantine/"
```
After editing, run `omamori test` to verify. Disabled rules show as `SKIP`:
```
Rules:
...
Summary: 5 rules (4 active, 1 disabled), 4 detection tests passed
```
### Configuration notes
- Config file requires `chmod 600` (permissions check enforced)
- Only write rules you want to change — everything else is inherited
- `destination` must be an absolute path on the same volume
- System directories (`/usr`, `/etc`, `/System`, `/Library`, `/bin`, `/sbin`, `/var`, `/private`) are blocked as destinations
- Symlinks are rejected as destinations
- `destination` directory must exist before use (omamori will not create it)
## Available Actions
| `trash` | Move targets to macOS Trash |
| `move-to` | Move targets to a user-specified directory (requires `destination`) |
| `stash-then-exec` | Run `git stash` first, then execute the original command |
| `block` | Refuse to execute |
| `log-only` | Log the event, then execute normally |
## Safe Defaults
| No AI env var detected | Pass through to real command (no interference) |
| Config file missing | Fail-close: built-in default rules apply |
| Config file broken | Fail-close: built-in default rules apply + warning |
| Trash / move-to fails | Fail-close: refuse to run the original command |
| `sudo` detected | Block the command |
| Blocked destination | Fail-close: rule is disabled at config load time |
| Shim binary crashes | Fail-open: real command runs |
## CLI
```
omamori test [--config PATH] # Verify policy rules
omamori exec [--config PATH] -- <command> [args...] # Run through policy engine
omamori install [--base-dir PATH] [--hooks] # Create shims + hooks + config
omamori uninstall [--base-dir PATH] # Remove shims + hook files
omamori init [--force] [--stdout] # Create/reset config file
omamori config list # Show all rules with status
omamori config disable <rule> # Disable a built-in rule
omamori config enable <rule> # Re-enable a disabled rule
```
## Structural Limitations
These are inherent to the PATH shim approach and documented honestly:
- **Full-path execution** (`/bin/rm`, `/usr/bin/git`) bypasses the shim — partially mitigated by Layer 2 hooks
- **`sudo`** changes PATH before the shim runs — omamori blocks when it detects elevated execution in-process
- **Other interpreters** (`python -c "os.remove(...)"`, `perl -e`) are not intercepted
- **Non-rm destructive commands** (`find -delete`, `rsync --delete`) are not covered
- **Cross-device moves** are not supported for `move-to` (use a destination on the same volume)
For the full security model, see [SECURITY.md](SECURITY.md).
## Related
- **[nanika](https://github.com/yottayoshida/nanika)** — explains what AI commands will do (detect + translate). Complementary to omamori (detect + replace).
## License
Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or [MIT license](LICENSE-MIT) at your option.