Skip to content
christopherkaraniPublic

About

rv blocks destructive shell commands from autonomous agents — 95 rule packs, on-device Laya-model judge, secrets & MCP governance, tamper-evident audit. Fail-closed. Never asks the agent.

Topics

Resources

Contributing

Security policy

Stars

7 stars

Watchers

1 watching

Forks

Repository files navigation

rv — shell guard for coding agents

Release Apache 2.0 Stars Discord 95 rule packs macOS 15+ Apple Silicon and Linux

rv

Your coding agent just tried to run rm -rf /. rv said no.

rv is a fail-closed policy gate for AI coding agents. It sits on your agent's pre-tool hook and blocks destructive shell commands — and secret-file reads/edits — before the host runs them. One gate, three verdicts: allow · deny · indeterminate. It never asks the agent; only you can override, with a one-time code.

$ rv test 'git reset --hard'
{"decision":"deny","pack_id":"core.git","reason":"git reset --hard destroys uncommitted changes","rule_id":"core.git:reset-hard","schema":"rv.test.v1"}

$ rv test 'git status'
{"decision":"allow","schema":"rv.test.v1"}

Install (30 seconds)

curl -fsSL https://rykanv.com/install | sh
rv setup    # auto-detects your agents and wires their hooks
rv doctor   # verify everything is live

On macOS the installer also fetches the on-device judge weights (~649 MB, verified by SHA-256, fully offline after) so the neural judge binds on first run; Linux installs run packs-only until the ONNX runtime lands. Re-run the installer anytime to pick up the weights.

Works with Claude Code, Codex, Cursor, Grok, OpenCode, Pi, Hermes, OpenClaw, Antigravity, and Muse. Hooks are only written for hosts already on your machine. Requires macOS 15+ (Apple Silicon) or Linux (aarch64/x86_64).

How it works

Every shell and file-tool call from every host funnels into one daemon (rvd) and one pipeline:

agent ─▶ hook ─▶ rvd ─▶ 95 rule packs ─▶ script gate ─▶ on-device judge ─▶ policy ─▶ allow / deny
                          safe-first       npm bodies     CoreML (Laya)      overrides
                          deny = floor     evaluated      can only raise
  • 95 rule packs — git, filesystem, disks, cloud CLIs, Kubernetes, databases, Terraform, CI/CD, payments, and more. Safe patterns run first; the first blocking hit denies. Three packs are on by default (core.filesystem, core.git, system.disk); browse the rest with rv packs; rv packs enable <id> turns more on after owner authentication (see below).
  • Script gate — npm test can't hide a payload: rv evaluates the actual pre/post/body scripts in package.json, not just the command you see.
  • On-device neural judge — with a Laya CoreML bundle installed, pack-allowed commands get a local risk score. The judge can only raise a verdict, never lower a pack deny. Nothing leaves your machine. "guard.mode": "observe" logs would-be verdicts without blocking, so you can measure before you enforce. rv host mode <host> observe does the same for one host (off unwires it); rv blocks marks what observe would have blocked with "observed": true. Observe never relaxes rv's own protection (rv admin commands, rv's config). A host set off before an organization gate arrived stays unwired until you run rv setup.
  • Policy gate — a fixed override ladder (rebase recovery → pinned rules → allowlist → allow-once → contained-delete allowance) with normal/strict safety levels. Indeterminate (too large, budget exhausted, core packs missing) is never overridable.

What gets blocked

Category Examples
Destructive git reset --hard, push --force, clean -fd, stash clear, checkout -- .
Destructive filesystem rm -rf /, rm -rf ~, find -delete, fork bombs, disk wipes
Secret paths .env, SSH keys, cloud credentials — shell and Read/Edit/Write on Grok, Claude, Cursor
Cloud & infra (opt-in packs) terraform destroy, kubectl delete, aws s3 rm --recursive, DROP TABLE, …

Not sure why something blocked? rv explain 'git reset --hard' shows exactly which pack and rule fired.

Known limitations: search tools. rv gates explicit secret paths and secret-selecting globs in search tools (Claude Grep/Glob, Cursor Grep). A search with no explicit path scans the working directory and can still match inside non-ignored secret files there, because rv does not inspect file contents.

Vault secrets. A secret definition with an address is refused unless VAULT_ADDR is set to the same origin: rv never sends your Vault token to a server the environment does not name.

When you're blocked (and you meant it)

Every hook deny prints a six-character code. Redeem it once, from your terminal — the agent can't redeem its own code:

rv allow-once a1b2c3    # next matching call in this directory runs once

Redeeming needs owner authentication: Touch ID or your password through the signed CLI on macOS, your login password on Linux.

Typed rules live in ~/.config/rv/policy.toml (rv policy show). Commands that change the gate itself (rv allowlist add, rv packs enable, rv safety strict|normal, rv policy draft --save, rv egress approve, rv workspace abandon) ask for the same owner authentication first, so an agent running as you cannot weaken its own guard through rv. The config files themselves are still yours to write: rv's hook guard refuses an agent's attempts to edit them, but the CLI, not rvd, performs the change after approval. On Linux rv reads your login password from the terminal and rvd checks it with the system's unix_chkpwd; five wrong passwords in ten minutes lock checks for ten minutes. Every attempt is recorded as an owner.action event in the audit log.

Beyond the shell

rv is one binary, 25 commands. The rest of the surface:

  • Secrets without exposure — agents in a contained workspace (macOS) see placeholders, never values. Real bytes are injected at the boundary from Keychain, 1Password, Vault, AWS/GCP/Azure, Infisical, or Bitwarden, then scrubbed from everything that comes back. Hook-guarded agents get secret-path blocking instead; stdio MCP servers receive the real value. rv secrets scan + a git pre-commit hook catch leaks before they land.
  • App logins, once — rv login connect vercel imports the Vercel or GitHub login you already have (CLI auth file, token variable, or gh auth token; paste as fallback) into the Keychain as a gateway secret, so agents use it through rv instead of logging in again. rv login list / check report status and fingerprints, never values; rv login logout <app> removes it.
  • MCP governance — rv mcp serve puts every MCP server behind one gateway with per-tool allow/ask/deny, human approval for ask, and a full audit trail. rv mcp check fails if any server bypasses rv.
  • Egress control — contained runtimes reach the network only through a credentialed CONNECT proxy: per-runtime tokens, SNI-bound tunnels and binary pinning. Blocked hosts are queued for review (rv egress); rv egress approve asks for owner authentication.
  • Tamper-evident audit — every hook and file-tool deny, every override (allow-once, allowlist, rebase recovery), plus MCP and secret events, lands in a SHA-256 hash-chained audit.jsonl (rule and host, never command text). Verify with rv audit verify, export as OCSF 1.3.0 to your SIEM.
  • Session forensics — rv scan replays past agent sessions (Claude, Codex, Cursor, Grok, Hermes, OpenClaw, OpenCode, Pi) offline and reports which commands your enabled packs would have denied.
  • Signed org policy — fleet-wide, restrict-only rules signed with Ed25519 and pinned root-owned on disk: MCP tool rules, secret sources, audit forwarding, and gate requirements (packs every agent must run under, strict safety). User config can never loosen them. rv report emits posture for MDM/fleet collection.
  • Contained workspaces (macOS) — rv opencode / rv workspace run agents on a persistent per-project host under a deny-default Seatbelt profile: workspace-only writes, proxied HTTPS, no Keychain, no host signals, and the same packs you enabled for your agents. rv workspace run --microvm <image> runs the command in a network-less Linux micro-VM instead (macOS 26+). Linux hosts refuse rather than downgrade. This is a hardening layer, not a finished isolation boundary — see the acceptance audit.

Everyday commands

rv test 'rm -rf /'          # evaluate a command, don't run it
rv explain 'rm -rf /'       # why would this block?
rv packs                    # browse the 95 packs
rv blocks                   # what got denied lately?
rv host list                # per-host mode (block / observe / off) and wiring
rv workspace vms            # micro-VM runtime sessions, newest first
rv scan                     # audit past agent sessions
rv audit verify             # check the audit hash chain
rv doctor                   # service, packs, hosts, judge health
rv uninstall                # remove everything rv owns (owner-auth)

All commands speak --json / --robot / --plain / --no-color. Anonymous usage counters are on by default; opt out with "analytics.enabled": false (or {"analytics": {"enabled": false}}) in ~/.config/rv/config.json.

For developers

git clone https://github.com/christopherkarani/rv && cd rv
swift build --build-tests   # Swift 6.4
swift test                  # full suite (this is the PR gate)

Architecture in one line: a tiny C front door (rv) execs the Swift CLI, which talks to the rvd daemon over a Unix socket (XPC on macOS) — 15 IPC methods, one gated evaluation path for every door. A Python SDK lives in sdk/python. Security model and evidence: docs/security. Before opening a PR, read CONTRIBUTING.md; report vulnerabilities per SECURITY.md.

Site: rykanv.com · Docs: rykanv.com/docs/introduction · Discord: discord.gg/uZn9MDUYKx

License

Apache 2.0. See LICENSE.

About

rv blocks destructive shell commands from autonomous agents — 95 rule packs, on-device Laya-model judge, secrets & MCP governance, tamper-evident audit. Fail-closed. Never asks the agent.

Topics

Resources

Contributing

Security policy

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages