Skip to content
| Marketplace
Sign in
Visual Studio Code>Linters>Anvil — Protect Risky CallsNew to Visual Studio Code? Get it now.
Anvil — Protect Risky Calls

Anvil — Protect Risky Calls

anvilcontrol

| (0) | Free
Inline protection for the risky calls, agents, and workflows in your code. Wrap them where you write them, then watch and enforce from your Anvil control plane. Works in VS Code and Cursor.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Anvil — Protect Risky Calls (VS Code / Cursor)

Your code, and the AI agents you ship, take real actions in real systems: they move money, call APIs, write to your database, run workflows. Without limits, one wrong step becomes a real incident: a runaway bill, a deleted table, a leak you can't take back.

Anvil is the boundary those actions run through, and this extension brings it into your editor. Put your cursor on a risky call, an agent action, or a workflow, press Protect, and it's wrapped: safe to retry, wired to your control plane.

Every wrap starts in ghost mode: the real call runs, Anvil watches and records, nothing is blocked yet. Flip it to enforce from your dashboard when the proof is obvious, and the boundary holds: no double-charge, no overspend, no action it shouldn't take. Undo anytime with Cmd/Ctrl+Z.

No account to start: install, wrap a call, watch it in ghost. Connect your control plane (Anvil: Connect to your control plane) when you want ghost and enforce to sync live.

Five ways to protect a call

All produce the byte-identical wrap (same codemod as the Anvil CLI and MCP server):

Trigger When to use
CodeLens "Protect verb — why" above the call One click; appears automatically on recommended calls
Right-click → Protect with Anvil On the call your cursor is on (any call, not just recommended)
Cmd+Alt+A (Ctrl+Alt+A on Windows/Linux) Keyboard. Recommended/write calls wrap instantly; read-looking calls (db.query, getUser …) confirm first so you don't silently wrap a read
Cmd+Shift+P → "Anvil" Command palette
Type anvil (or protect) on a call line IntelliSense offers an Anvil completion that wraps that line's call

Lifecycle (the inline icon tells you the state)

State Inline icon Meaning
Unprotected grey anvil, on the lens Anvil suggests protecting this; nothing's wrapped yet
Ghost a ghost, before the call Wrapped, watching only: it records duplicates and blocks nothing. Lens above offers "Enforce verb?"
Enforce a blue anvil, before the call Live and enforcing the boundary. Lens above offers "Back to ghost?"

The blue anvil is the earned state: it appears only when Anvil is actually enforcing.

What it does on Apply

  1. Computes the wrap in memory and (for menu/lens) shows a side-by-side diff preview.
  2. Writes a single undoable edit (WorkspaceEdit).
  3. Picks a durable idempotency key from the call's first argument (orderId, paymentIntentId, userId, …). If none can be inferred, it inserts a // TODO(anvil) and lands your cursor on the key so you can type the real id.
  4. Folds the wrap boilerplate so the result is a clean, readable line.
  5. Offers to install @useanvil/sdk if it's not already a dependency.

Never auto-wraps. Never writes without confirmation (except the keyboard shortcut on already-recommended calls, which applies directly — Cmd+Z to undo).

Settings

  • anvil.enable — turn the lenses/actions on or off (default: on).
  • anvil.riskyActions — extra glob patterns to treat as risky, e.g. ["*.runTool", "queue.publish"] (added to the built-in money + destructive taxonomy).
  • anvil.includeComms — also flag email/SMS sends (off by default).
  • anvil.includeSideEffects — also flag generic side-effects: webhooks, queue publishes, database writes, external API mutations (webhook.publish, queue.enqueue, api.post, db.upsert). Off by default so Anvil flags only the highest-confidence calls (money, destructive) with no false positives. On, it stays precise: strong external verbs flag alone, ordinary mutating verbs flag only in an external-system context, and collections/logs/reads (array.push, map.set, logger.write) never flag.
  • anvil.controlPlaneUrl — origin of your Anvil control plane. One origin serves both the dashboard UI (/app, opened by View in Anvil) and the API the editor talks to. Leave blank to use the hosted Anvil control plane (the default). Point it at your own deployment (e.g. https://your-app.up.railway.app) or http://localhost:7446 for a local control plane. Commit it to .vscode/settings.json so your whole team targets the same control plane.
    • Deprecated overrides (still honored for back-compat): anvil.dashboardUrl overrides just the View in Anvil page URL, and anvil.apiUrl overrides just the API base URL — useful for a split dev setup (e.g. a dashboard mockup on :8088 with the API on :7446). Prefer anvil.controlPlaneUrl; a value in either deprecated key wins over the derived origin.

Zero-config local plane

When anvil.controlPlaneUrl is blank and no token is set, the editor connects to a control plane on your machine on its own — install, wrap a call, watch it get tracked, nothing to run by hand. Three machine-scoped settings govern it:

  • anvil.autoConnectLocalPlane — detect a plane already running on localhost and read ghost/enforce from it over http://127.0.0.1, no token (control reads are open on loopback). On by default. Off keeps the editor on the optimistic ghost default until you connect. Only auto-detect is affected — an explicit localhost anvil.controlPlaneUrl is always honored.
  • anvil.autoStartLocalPlane — start one when none is running. In an Anvil project (the CLI is installed) with no plane on the port, the editor runs anvil serve in the background; it stays up as your local dashboard, single-instance, loopback only. On by default. Off keeps the editor from ever starting a server. Anvil: Start local control plane works either way.
  • anvil.localPlanePort — the port to find and start the local plane on (default 7446). Change only if you run yours elsewhere.

Control token (secure)

Pointing the editor at a control plane that requires auth — a self-hosted deployment behind ANVIL_CONTROL_TOKEN — takes one command: Anvil: Sign in / Set control token (Cmd/Ctrl+Shift+P → "Anvil"). The token is kept in the editor's secret storage, never in settings.json, and is handed to the anvil CLI as ANVIL_CONTROL_TOKEN for control-plane requests. Leave the box blank to keep the current token, or to remove it.

Without a token the editor stays local-only — it reads and writes your local control plane exactly as before. A status-bar item tells you which: a key when a token is configured, local only if you removed one. The token is never printed to logs, and "Sign in with Anvil" (Google) will land in the same command once hosted auth ships.

Troubleshooting

No lenses on a file you expected to be flagged? Open View → Output → "Anvil". The channel logs slow parses (>250 ms), skipped large files (>250 KB), and codemod errors with the file path so you can see why.

The keyboard shortcut opens a search bar? Cursor binds many Cmd+Shift combos to its own search. The default is Cmd+Alt+A; rebind via Cmd+K, Cmd+S → search "Anvil" → press your preferred keys.

Ghost/enforce toggle says "couldn't reach control plane"? The toggle shells out to the anvil CLI, which needs Redis. The lens still reflects state correctly; only the flip needs the backend.

Install

From the marketplace (recommended). Search "Anvil — Protect Risky Calls" in the Extensions view, or from a terminal:

code   --install-extension anvilcontrol.anvil-protect   # VS Code
cursor --install-extension anvilcontrol.anvil-protect   # Cursor / VSCodium (via Open VSX)

VS Code installs from the Visual Studio Marketplace; Cursor and VSCodium pull the same build from Open VSX.

From a .vsix (offline / pre-release). Build with npm run package, then Extensions → … → Install from VSIX. Cursor runs VS Code extensions unmodified, so one build covers both.

Maintainers: RELEASE_CHECKLIST.md documents how releases are published.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft