How to give Claude Code access to your API without giving it your keys
Claude Code works best when it can call the API it is changing. The usual shortcut puts a production key in the agent's settings or an .env file, where the agent and anything it runs can read it.
Porticol Guard gives the agent the API without the key. Calls go through Porticol's MCP server, the key is injected inside Porticol, and a risky call waits for you.
1. Install
macOS or Linux:
curl -fsSL https://porticol.app/install.sh | sh
Windows, in PowerShell:
irm https://porticol.app/install.ps1 | iex
Open Porticol. Local use needs no account and no sign-in. An account is asked for only when you invite someone, sync, share or use a team gateway.
2. Connect Claude Code
On the start screen, choose Connect my coding agent. Porticol finds Claude Code, shows the exact lines it will add to ~/.claude.json, and writes nothing until you click Add Porticol. Remove restores the file.
By hand, add the server at user scope:
claude mcp add --scope user porticol -- porticol-cli mcp
Restart Claude Code or reload MCP, then ask it to list your Porticol collections. The first call proves the connection.
For level 2 on macOS or Linux, let Porticol add the sandbox settings: the sandbox on, sandbox.network.httpProxyPort pointing at the local proxy, read denied for .env*, ~/.aws, ~/.config/gcloud and similar, and a PreToolUse hook that fails closed. The screen shows every line before it writes one.
3. Write a policy
Guard reads one YAML policy. Start in shadow mode, where Guard logs what it would do and lets the call through, then switch to enforce when the rules match how your team works. The policy below is in enforce, because the walkthrough holds a call.
version: 1
mode: enforce
hosts:
api.example.com: { env: production, key: "{{api_key}}" }
rules:
- match: { method: [GET, HEAD] }
action: allow
- match: { env: production, method: [POST, PUT, PATCH] }
action: ask
agents:
claude-code: { up_to: production }
"*": { up_to: staging }
{{api_key}} names a secret variable of the production environment. Its value stays in the keychain, and Porticol adds it to the request.
The first matching rule wins. A call above the agent's ceiling is denied before any rule. On a protected environment, a call no rule matches asks by default, so a DELETE to production is held.
4. The held call
When Claude Code sends a DELETE to production, send returns:
{
"status": "pending",
"approval_id": "8f0c…",
"reason": "DELETE to production needs a person.",
"message": "A person must approve this call in Porticol. Call send again with the same request and approval_id once they have. Do not loop and do not ask for a secret."
}
The approval card shows the agent's name, the environment, the exact request with keys masked, and the agent's reason in its own words. Choose Allow once, Allow for today or Deny. A system notification fires while the app is in the background. From a terminal, porticol-cli approve <id> takes the four-letter code shown on the card; the agent's shell has no terminal, so it cannot approve its own call.
The approval is bound to a SHA-256 of the request the policy decided: the method, URL, environment, headers, auth, protocol, settings and body. It is single use and expires after 10 minutes. Claude Code retries once with the same request and approval_id; a changed request does not match. A denied call returns {"status": "denied"} and is not retried.
5. Read the log
Every call lands in Agent activity: the agent, method, URL, environment, decision and the rule behind it. The same entries sit in a hash-chained log. porticol-cli guard log verify checks the chain, and the log exports as JSON or CSV. Free keeps 30 days on this computer; on the server, Team keeps 90 days and Business 180, with export.
The honest limit for Claude Code
Level 1 stops mistakes. An agent that finds a production key outside Porticol and runs curl itself is not stopped. Level 2 closes that on macOS and Linux by forcing sandboxed Bash through the proxy, but the sandbox covers Bash only: file tools, MCP servers, WebFetch and hooks run outside it, and a person can turn the sandbox off unless managed settings forbid it. Windows runs levels 1 and 3 only. Claude Code's name in the log is self-reported.
Questions
Does Claude Code ever see the key? No. The key is injected inside Porticol when the request is sent, and every result is masked. A key that already sits in an .env file is a separate problem: porticol-cli guard scan finds those, and Porticol offers to move each value to the keychain.
What happens if nobody answers? The MCP call waits up to 45 seconds, then returns pending with the approval id. The approval stays open for 10 minutes, and the agent may retry once after you approve it.
Can I approve from a terminal? Yes. Run porticol-cli approve <id> and type the four-letter code from the card. An agent's shell has no terminal, which is the point.