@melihmucuk/leash
v1.0.6
Published
Security guardrails for AI coding agents
Maintainers
Readme
Leash 🔒
Security guardrails for AI coding agents. Sandboxes file system access, blocks dangerous commands outside project directory, prevents destructive git operations, catches agent hallucinations before they cause damage.
Why Leash?
AI agents can hallucinate dangerous commands. Leash sandboxes them:
- Blocks
rm,mv,cp,chmodoutside working directory - Protects sensitive files (
.env,.git) even inside project - Blocks
git reset --hard,push --force,clean -f - Resolves symlinks to prevent directory escapes
- Analyzes command chains (
&&,||,;,|)

Example horror stories
Links:
- Claude CLI deleted my entire home directory (Dec 8th 2025)
- Google Antigravity just deleted my drive (Nov 27th 2025)
Quick Start
# Install leash globally
npm install -g @melihmucuk/leash
# Setup leash for your platform
leash --setup <platform>
# Remove leash from a platform
leash --remove <platform>
# Update leash anytime
leash --update| Platform | Command |
| --------------- | --------------------------- |
| OpenCode | leash --setup opencode |
| Pi Coding Agent | leash --setup pi |
| Claude Code | leash --setup claude-code |
| Factory Droid | leash --setup factory |
Restart your agent. Done!
If you prefer manual configuration, use leash --path <platform> to get the path and add it to your config file.
Pi Coding Agent - docs
Add to ~/.pi/agent/settings.json:
{
"hooks": ["<path from leash --path pi>"]
}OpenCode - docs
Add to ~/.config/opencode/opencode.json (or opencode.jsonc if you use that):
{
"plugin": ["<path from leash --path opencode>"]
}Claude Code - docs
Add to ~/.claude/settings.json:
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "node <path from leash --path claude-code>"
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash|Write|Edit",
"hooks": [
{
"type": "command",
"command": "node <path from leash --path claude-code>"
}
]
}
]
}
}Factory Droid - docs
Add to ~/.factory/settings.json:
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "node <path from leash --path factory>"
}
]
}
],
"PreToolUse": [
{
"matcher": "Execute|Write|Edit",
"hooks": [
{
"type": "command",
"command": "node <path from leash --path factory>"
}
]
}
]
}
}What Gets Blocked
# Dangerous commands outside working directory
rm -rf ~/Documents # ❌ Delete outside working dir
mv ~/.bashrc /tmp/ # ❌ Move from outside
echo "data" > ~/file.txt # ❌ Redirect to home
# Protected files (blocked even inside project)
rm .env # ❌ Protected file
echo "SECRET=x" > .env.local # ❌ Protected file
rm -rf .git # ❌ Protected directory
# Dangerous git commands (blocked everywhere)
git reset --hard # ❌ Destroys uncommitted changes
git push --force # ❌ Destroys remote history
git clean -fd # ❌ Removes untracked files
# File operations via Write/Edit tools
~/.bashrc # ❌ Home directory file
../../../etc/hosts # ❌ Path traversal
.env # ❌ Protected fileWhat's Allowed
rm -rf ./node_modules # ✅ Working directory
rm -rf /tmp/build-cache # ✅ Temp directory
rm .env.example # ✅ Example files allowed
git commit -m "message" # ✅ Safe git commands
git push origin main # ✅ Normal push (no --force)
echo "plan" > ~/.claude/plans/x # ✅ Platform config directories
rm ~/.pi/agent/old.md # ✅ Platform config directoriesDangerous Commands
rm -rf ~/Documents # ❌ Delete outside working dir
mv ~/.bashrc /tmp/ # ❌ Move from outside
cp ./secrets ~/leaked # ❌ Copy to outside
chmod 777 /etc/hosts # ❌ Permission change outside
chown user ~/file # ❌ Ownership change outside
ln -s ./file ~/link # ❌ Symlink to outside
dd if=/dev/zero of=~/file # ❌ Write outside
truncate -s 0 ~/file # ❌ Truncate outsideDangerous Git Commands
git checkout -- . # ❌ Discards uncommitted changes
git restore src/file.ts # ❌ Discards uncommitted changes
git reset --hard # ❌ Destroys all uncommitted changes
git reset --hard HEAD~1 # ❌ Destroys commits and changes
git reset --merge # ❌ Can lose uncommitted changes
git clean -f # ❌ Removes untracked files permanently
git clean -fd # ❌ Removes untracked files and directories
git push --force # ❌ Destroys remote history
git push -f origin main # ❌ Destroys remote history
git branch -D feature # ❌ Force-deletes branch without merge check
git stash drop # ❌ Permanently deletes stashed changes
git stash clear # ❌ Deletes ALL stashed changesRedirects
echo "data" > ~/file.txt # ❌ Redirect to home
echo "log" >> ~/app.log # ❌ Append to home
cat secrets > "/tmp/../~/x" # ❌ Path traversal in redirectCommand Chains
echo ok && rm ~/file # ❌ Dangerous command after &&
false || rm -rf ~/ # ❌ Dangerous command after ||
ls; rm ~/file # ❌ Dangerous command after ;
cat x | rm ~/file # ❌ Dangerous command in pipe
cd ~/Downloads && rm file # ❌ cd outside + dangerous command
cd .. && cd .. && rm target # ❌ cd hops escaping working dirWrapper Commands
sudo rm -rf ~/dir # ❌ sudo + dangerous command
env rm ~/file # ❌ env + dangerous command
command rm ~/file # ❌ command + dangerous commandCompound Patterns
find ~ -name "*.tmp" -delete # ❌ find -delete outside
find ~ -exec rm {} \; # ❌ find -exec rm outside
find ~/logs | xargs rm # ❌ xargs rm outside
find ~ | xargs -I{} mv {} /tmp # ❌ xargs mv outside
rsync -av --delete ~/src/ ~/dst/ # ❌ rsync --delete outsideProtected Files (blocked even inside project)
rm .env # ❌ Environment file
rm .env.local # ❌ Environment file
rm .env.production # ❌ Environment file
echo "x" > .env # ❌ Write to env file
rm -rf .git # ❌ Git directory
echo "x" > .git/config # ❌ Write to git directory
find . -name ".env" -delete # ❌ Delete protected via findNote: .env.example is allowed (template files are safe).
File Operations (Write/Edit tools)
/etc/passwd # ❌ System file
~/.bashrc # ❌ Home directory file
/home/user/.ssh/id_rsa # ❌ Absolute path outside
../../../etc/hosts # ❌ Path traversal
.env # ❌ Protected file
.git/config # ❌ Protected directoryWhat's Allowed (Full List)
# Working directory operations
rm -rf ./node_modules
mv ./old.ts ./new.ts
cp ./src/config.json ./dist/
find . -name "*.bak" -delete
find ./logs | xargs rm
# Temp directory operations
rm -rf /tmp/build-cache
echo "data" > /tmp/output.txt
rsync -av --delete ./src/ /tmp/backup/
# Platform config directories
rm ~/.claude/plans/old-plan.md
echo "config" > ~/.factory/cache.json
rm ~/.pi/agent/temp.md
rm ~/.config/opencode/cache.json
find ~/.claude -name '*.tmp' -delete
rsync -av --delete ./src/ ~/.pi/backup/
# Device paths
echo "x" > /dev/null
truncate -s 0 /dev/null
# Read from anywhere (safe)
cp /etc/hosts ./local-hosts
cat /etc/passwd
# Safe git commands
git status
git add .
git commit -m "message"
git push origin main
git checkout main
git checkout -b feature/new
git branch -d merged-branch # lowercase -d is safe
git reset --soft HEAD~1 # soft reset is safe
git restore --staged . # unstaging is safe
git stash
git stash popPerformance
Near-zero latency impact on your workflow:
| Platform | Latency per tool call | Notes | | ----------- | --------------------- | ---------------------------------------- | | OpenCode | ~20µs | In-process plugin, near-zero overhead | | Pi | ~20µs | In-process hook, near-zero overhead | | Claude Code | ~31ms | External process (~30ms Node.js startup) | | Factory | ~31ms | External process (~30ms Node.js startup) |
For context: LLM API calls typically take 2-10+ seconds. Even the slower external process hook adds less than 0.3% to total response time.
Limitations
Leash is a defense-in-depth layer, not a complete sandbox. It cannot protect against:
- Kernel exploits or privilege escalation
- Network-based attacks (downloading and executing scripts)
- Commands not routed through the intercepted tools
For maximum security, combine Leash with container isolation (Docker), user permission restrictions, or read-only filesystem mounts.
Development
cd ~/leash
npm install
npm run buildContributing
Contributions are welcome! Areas where help is needed:
- [ ] Plugin for AMP Code
Keep your AI agents on a leash.
