shellgate
v3.0.2
Published
Secure shell execution for AI agents — MCP server + CLI
Maintainers
Readme
AI agents need shell access. Direct exec() is a security nightmare — one malformed prompt, arbitrary execution. Shellgate bridges the gap: a 5-layer security model that lets Claude run whitelisted commands safely — gh, git, npm, curl — with full audit logging and zero shell interpolation.
Platform: macOS ✅ · Linux 🔄 planned · Windows 📋 planned
Core logic is platform-agnostic. Linux support is next — shell detection and path handling already abstract over the OS. Windows (PowerShell) is on the roadmap for v4.0.
Why not just exec()?
| | exec() / shell: true | Shellgate |
|---|---|---|
| Shell injection | ❌ Vulnerable | ✅ Blocked at layer 3 |
| Arbitrary commands | ❌ Anything runs | ✅ Whitelist only |
| Sensitive env vars | ❌ Leaks tokens | ✅ Auto-redacted |
| Audit trail | ❌ None | ✅ JSONL with rotation |
| Context profiles | ❌ One size fits all | ✅ interactive / scheduled / computer_use |
| Multi-agent isolation | ❌ Shared access | ✅ Per-agent permission scope |
| AI self-correction | ❌ Raw errors | ✅ Actionable error suggestions |
How it works
┌──────────────────────────────────────────────────────────────────┐
│ Claude Desktop │
└────────────────────────────────┬─────────────────────────────────┘
│ MCP (stdio transport)
▼
┌──────────────────────────────────────────────────────────────────┐
│ Shellgate MCP │
│ │
│ ① Whitelist → ② Subcommand → ③ Injection → ④ Path │
│ check filter guard check │
│ │
│ ⑤ execFile(shell: false) │
│ args as array — no shell │
└────────────────────────────────┬─────────────────────────────────┘
│
┌─────────────────────┼──────────────────────┐
▼ ▼ ▼
git / gh curl / jq npm / nodeQuick start
# Install globally
npm install -g shellgate
# Auto-detect AI environments and configure
shellgate setupDetects Claude Desktop, Claude Code, and Cowork — configures all automatically.
Or configure manually — add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"shellgate": {
"command": "npx",
"args": ["-y", "shellgate@latest", "serve"]
}
}
}Restart Claude Desktop. Done.
CLI
# Execute commands
shellgate exec git -- status # run a whitelisted command
shellgate exec git -- log --oneline # with args
shellgate exec npm -- run build # build your project
shellgate batch --file cmds.json # run multiple commands in parallel
# Configure (interactive TUI or direct subcommands)
shellgate config # interactive config panel (TTY)
shellgate config allow docker --tier SAFE --readonly
shellgate config block rm
shellgate config agent claude-code --commands "git,npm" --tools "shellgate_execute"
shellgate config profile dispatch --timeout 60000 --filter readonly --create
shellgate config defaults --timeout 15000
shellgate config reset --preset developer --yes
shellgate config --show # full JSON dump
shellgate config edit # open in $EDITOR
shellgate init # setup wizard (optional)MCP Tools
| Tool | When to use | Hint |
|---|---|---|
| shellgate_execute | Run any whitelisted command — single or batch | 🔴 Destructive |
| shellgate_briefing | Collect data from multiple sources in one parallel call | 🟢 Read-only |
| shellgate_file | Read/write/glob files, with optional pipeline engine | 🔴 Destructive |
| shellgate_config | Inspect config, profiles, agents, audit log | 🟢 Read-only |
| shellgate_list_commands | List available commands and permissions | 🟢 Read-only |
Tip: Call
shellgate_list_commandsif you're unsure whether a command is whitelisted.
Batch mode — run multiple commands in one call, in parallel:
{
"batch": [
{ "label": "git", "command": "git", "args": ["status"] },
{ "label": "npm", "command": "npm", "args": ["run", "build"] },
{ "label": "gh", "command": "gh", "args": ["pr", "list"] }
]
}Pipeline mode — chain file operations in one call:
{
"action": "pipeline",
"steps": [
{ "op": "glob", "pattern": "~/Projects/*/package.json" },
{ "op": "read_all" },
{ "op": "jq", "filter": ".[] | select(.result.version)" },
{ "op": "filter", "predicate": "workspace" }
]
}Token efficiency
Every MCP tool call re-transmits the full conversation context. Sequential calls multiply your token cost — the longer the session, the worse it gets.
Shellgate is engineered to collapse N round-trips into 1.
Without batch — 3 separate calls:
Claude host
│ │
│── exec git status ──────▶│
│◀─ result ────────────────│ ← context re-sent (~10k tokens)
│ │
│── exec npm test ────────▶│
│◀─ result ────────────────│ ← context re-sent (~11k tokens)
│ │
│── exec docker ps ───────▶│
│◀─ result ────────────────│ ← context re-sent (~12k tokens)
│ │
total: ~33k tokens transmittedWith shellgate_execute batch — 1 call:
Claude host
│ │
│── exec --batch ─────────▶│
│ · git status ├──▶ parallel
│ · npm test ├──▶ parallel
│ · docker ps ─────────┤──▶ parallel
│ │
│◀─ 3 results ─────────────│ ← context sent once (~10k tokens)
│ │
total: ~10k tokens transmitted (-70%)The same pattern applies to shellgate_briefing (parallel data collection) and shellgate_file pipelines (glob → read_all → jq in a single call).
| Feature | Without | With Shellgate |
|---|---|---|
| 3 shell commands | 3 calls · 3× context | --batch · 1 call |
| 5 data sources | 5 sequential calls | briefing · 1 parallel call |
| glob → read → filter | 3 chained calls | pipeline · 1 call |
| Long session (50 turns) | Cost grows linearly | Batch keeps it flat |
Security model
🛡️ Layer 1 — Command whitelist Only commands in config.commands can run
🔍 Layer 2 — Subcommand filter git status ✅ git push ⚠️ (configurable)
💉 Layer 3 — Injection guard Blocks ; | & $ ` > < \n $(
📁 Layer 4 — Path restriction Files must be within allowed directories
⚙️ Layer 5 — execFile(shell:false) No shell spawned. Args passed as array.Even if an attacker controls argument values, there is no shell to interpret them.
Profiles
| Profile | Access | Use case |
|---|---|---|
| interactive | Full | Default — user sessions, Claude Desktop |
| scheduled | Read-only | Cron jobs, automation pipelines |
| computer_use | Full + osascript | UI automation agents |
| dispatch | Read-only + tracking | Multi-agent dispatch |
SHELLGATE_PROFILE=scheduled shellgate serveAgents
Each agent has an isolated permission scope. Effective permission = intersection of profile + agent.
{
"agents": {
"dev-assistant": {
"description": "Development assistant",
"tools": ["shellgate_execute", "shellgate_file"],
"commands": ["git", "npm", "cat", "ls"],
"file_paths": ["~/Projects"],
"file_ops": ["read", "write", "glob"]
}
}
}SHELLGATE_AGENT=dev-assistant shellgate serveConfiguration
Config file: ~/.config/shellgate/config.json — managed via CLI or interactive TUI, no manual editing needed.
Two configuration paths:
| | Humans | Agents / Scripts |
|---|---|---|
| How | shellgate config opens Ink TUI (React for CLI) | shellgate config allow/block/agent/... subcommands |
| When | Terminal (TTY detected) | Programmatic, pipeable, scriptable |
| Same result | Both call the same config-actions layer — zero logic duplication |
# Agent journey — fully programmatic setup
shellgate config allow git --tier SAFE --readonly --description "Git VCS"
shellgate config allow npm --tier SAFE --readonly --subcommands "run,test,install"
shellgate config block rm
shellgate config block sudo
shellgate config agent claude-code --commands "git,npm" --tools "shellgate_execute,shellgate_briefing"
shellgate config --show # verifyAll config subcommands:
shellgate config allow <cmd> Add to whitelist (--tier, --readonly, --mode, --subcommands)
shellgate config block <cmd> Add to forbidden list
shellgate config unblock <cmd> Remove from forbidden list
shellgate config remove <cmd> Remove from whitelist
shellgate config agent <name> Create/edit agent (--commands, --tools, --description, --delete)
shellgate config profile <name> Create/edit profile (--timeout, --filter, --create)
shellgate config defaults View/set defaults (--timeout, --max-output)
shellgate config reset Reset to defaults (--preset, --yes)
shellgate config edit Open in $EDITOR
shellgate config --show JSON dump
shellgate config --path Config file path
shellgate config --full Visual summary with all commands| Env var | Purpose |
|---|---|
| SHELLGATE_PROFILE | Active profile name |
| SHELLGATE_AGENT | Active agent name |
| SHELLGATE_CONFIG | Custom config file path |
Architecture
shellgate/
├── packages/
│ ├── core/ @shellgate/core — security, executor, config, context, shells
│ └── features/ @shellgate/features — audit logging, briefing, fileops, pipeline
└── apps/
├── mcp-server/ shellgate — 5 MCP tools, stdio transport, lazy loading
└── cli/ shellgate-cli — exec, serve, batch, config, initTypeScript monorepo · pnpm workspaces · ESM · Node ≥ 20 · Ink (React for CLI)
Roadmap
| Version | Focus | Status | |---|---|---| | v2.0 | Core MCP + CLI + 5-layer security | ✅ Released | | v3.0 | Unified distribution · setup TUI · esbuild bundles | ✅ Released | | v3.1 | Test suite · GitHub Actions CI · .mcpb extension | 🔄 Next | | v3.2 | Linux support · shell detection | 📋 Planned | | v3.3 | New tools · scheduled briefings · more presets | 📋 Planned | | v4.0 | Windows · PowerShell · web dashboard | 🌐 Future |
Features
- Zero-config install —
npm install -gandshellgate serve, works immediately - Interactive config TUI —
shellgate configopens an Ink-powered (React for CLI) interactive panel - Programmatic config —
shellgate config allow/block/agent/...for agents and scripts - 5-layer security — whitelist → subcommand → injection → path → execFile
- 4 execution profiles — context-aware permissions per environment
- Multi-agent isolation — per-agent tool, command, and path scopes
- Batch mode — N commands in 1 MCP call,
Promise.allSettledin parallel - Pipeline engine — glob → read_all → jq → filter → write in 1 call
- Audit log — JSONL with automatic size-based rotation
- Env var redaction — tokens and secrets never appear in logs or responses
- Actionable errors — every error includes a suggestion for AI self-correction
- Lazy tool loading — only core tools registered at startup, others on demand
- GEO-optimized descriptions — tool descriptions tuned for AI routing accuracy
Contributing
Found a bug? Have an idea? PRs and issues are welcome. 🙌
Shellgate follows a strict GitFlow — feature branches, conventional commits, no direct pushes to main.
Read the Contributing Guide before opening a PR.
If you're just starting out: bug fixes and preset additions are great first contributions.
npm · Issues · Roadmap · MCP Protocol · MIT License
Built with the Model Context Protocol SDK
Maugus ✌️
