Install
$ agentstack add mcp-generalized-labs-ironrun ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
ironrun
Manage project environments in the terminal and let AI agents use secrets without reading them.
[](https://github.com/generalized-labs/ironrun/actions/workflows/ci.yml) [](https://goreportcard.com/report/github.com/generalized-labs/ironrun) [](https://github.com/generalized-labs/ironrun/blob/main/LICENSE)
ironrun is a local-first encrypted environment workspace. It gives humans one terminal UI for projects, environments, .env imports, and agent access. Trust an agent session once for a project’s dev environment, then it can work normally while ironrun injects values only into child processes and strips them back out of output before the agent sees them.
Your tests still get a live DATABASE_URL. The agent gets back exit_code: 0 and tests passed — and never the connection string.
Why you might want this
Coding agents (Claude Code, Codex, Cursor, and others) run shell commands on your machine, and those commands can see your environment. Most of the time that's fine. The problem is the small set of commands that print the environment:
printenv # dumps every env var, including secrets
cat .env # prints your local secrets file
echo $STRIPE_SECRET_KEY # a normal debugging step
docker inspect web # config blobs often contain credentials
When an agent runs one of these — often while legitimately debugging something you asked it to fix — the secret value lands in the chat transcript. From there it's in the model's context, it may be in the provider's logs, and it may be in a screen recording or a shared session. You can't un-send it, so the safe response is to rotate the credential.
This isn't hypothetical. From the Claude Code issue tracker:
> "Three confirmed incidents at one operator workstation in ~6 days. Each incident forced a credential rotation. None of these are exotic — they're shapes that came up during normal diagnosis work the model was asked to do." > — anthropics/claude-code#65122
The agents don't redact their own output, and the secret managers you already use (op run, doppler run, infisical run) inject secrets but don't redact either. ironrun adds the missing piece: it sits between the agent and the command so secrets flow in but never flow back out.
The threat you probably haven't seen yet
When Claude Code runs a command that uses a secret — a curl with an Authorization header, a deploy script that reads DATABASE_URL — that command invocation is logged verbatim to:
~/.claude/projects//YYYYMMDD_HHMMSS_*.jsonl
These JSONL files are Claude Code's conversation history. They contain every tool call, every shell command, every piece of output — including the secret values that appeared in those outputs. They persist between sessions and across project restarts.
One developer found this by accident:
> "It will just grep the logs and try to find a working secret from other projects/past sessions"
The logs are readable by any process with access to your home directory. If you've ever run a command through Claude Code that touched a secret, assume that value is in those logs.
ironrun redacts secret values from command output before it reaches the agent — so the values never enter the conversation, and never end up in the JSONL logs.
How it works
┌─────────────────────────────────────────────────────────────┐
│ AI agent (Claude Code, Codex, Cursor, …) │
│ │
│ "run the test suite" │
│ │ │
│ ▼ │
│ run_sealed({argv}) ◄── one MCP tool call │
│ │ │
└────────┼────────────────────────────────────────────────────┘
│ ironrun takes over here
▼
┌─────────────────────────────────────────────────────────────┐
│ ironrun │
│ │
│ 1. Check the human-approved project, dev environment, and │
│ current agent session │
│ 2. Resolve its encrypted environment entries │
│ 3. Run the command with those secrets injected │
│ 4. Stream output through a redactor: │
│ any secret value that appears → [REDACTED] │
│ 5. Hand back exit code + cleaned output │
│ │
│ Agent sees: exit_code=0, stdout="ok tests passed" │
│ Agent doesn't see: DATABASE_URL=postgres://… │
└─────────────────────────────────────────────────────────────┘
By default, an agent can use arbitrary argv only during a temporary session you explicitly trust. Strict policy commands remain available for CI, production, and sensitive projects. Ironrun never has a tool that returns a secret’s value.
> ironrun adds approximately 5-10ms per command invocation: ~2ms for provider lookup (env/envfile) up to ~100ms for a 1Password CLI call. The redaction layer adds under 1ms for typical output sizes.
Install
# curl (Linux/macOS — inspectable script, mandatory checksum verification)
curl -fsSL https://ironrun.dev/install.sh -o /tmp/ironrun-install.sh
bash /tmp/ironrun-install.sh
# Go (any platform)
go install github.com/generalized-labs/ironrun/cmd/ironrun@latest
# Verified npm launcher (Node 20+; native Go security boundary)
npx @generalized-labs/ironrun@latest
Windows (amd64) is a beta: download ironrun_Windows_x86_64.zip from the latest release and put ironrun.exe on your PATH.
Check it's on your path:
ironrun version
# ironrun 0.4.0 (a source build prints "ironrun dev")
Quickstart
Set up a project once:
cd your-project
ironrun setup
Setup previews every file it will write, detects .env key names without displaying values, creates an encrypted dev environment, registers MCP clients, and optionally installs the value-blind per-user service.
Then use bare ironrun from anywhere. It opens the global Projects and Inbox workspace. Agent requests appear automatically; Enter opens the exact review and resumes the waiting MCP call after approval or masked secret entry.
The everyday CLI is also intentionally short:
ironrun add OPENAI_API_KEY # masked prompt; saves to the active environment
ironrun import .env # preview names, confirm, encrypt, verify
ironrun new staging # create and switch to a persistent environment
ironrun session # create and switch to a 24-hour environment
ironrun use dev # switch environments
ironrun envs # list names and keys, never values
ironrun run test # run the approved command named "test"
ironrun trust list # inspect active trusted agent sessions
ironrun trust revoke ID # stop one immediately
ironrun status # value-blind project summary
Run ironrun setup when you also want project agent instructions and MCP configuration. It looks at your project and writes three files:
ironrun.yml— a starter policy. It detects your stack (npm/pnpm/yarn/bun, Go, Rust, Python) and your.env, and pre-fills commands liketest,dev, andbuildwith the env vars it found..mcp.json— wires Claude Code up to ironrun (project-scoped MCP server, merged into any existing file).CLAUDE.md,AGENTS.md,.cursorrules— tell the agent (Claude Code, Codex, Cursor) to run commands viarun_sealedinstead of typing them into a shell.
New policies bind approved commands directly to encrypted environment entry names. Storing or rotating a value never requires a policy edit:
version: "2"
environment_set: active
require_agent_leases: true
allow_proposals: true
commands:
- id: dev
argv: [npm, run, dev]
ttl: 0
secrets: [DATABASE_URL, STRIPE_SECRET_KEY]
- id: test
argv: [npm, test]
ttl: 120s
secrets: [DATABASE_URL, STRIPE_SECRET_KEY]
- id: build
argv: [npm, run, build]
ttl: 120s
Import or add values locally, then check the workspace:
chmod 600 .env
ironrun import .env
ironrun status
The import shows key names only, asks for confirmation, verifies the encrypted copy, and warns that the plaintext source remains. Ironrun never offers reveal, clipboard copy, or plaintext export.
Run one yourself to see the redaction:
ironrun run test
# npm test runs with DATABASE_URL and STRIPE_SECRET_KEY set.
# If a test logs the connection string, you'll see [REDACTED] instead.
Existing version-1 policies
Version-1 provider aliases remain supported. Preview a reversible migration:
ironrun migrate
ironrun migrate --apply
Migration copies values transactionally, verifies encrypted storage, preserves policy comments through an AST edit, keeps an ignored backup, and does not delete legacy values. ironrun migrate rollback ID remains available until an explicit ironrun migrate cleanup ID --yes.
Project environment sets
For projects with more than one environment, manage the values entirely from the terminal. On a new project, simply run ironrun: it creates a valid local-vault policy, registers the project identity, creates dev, and opens the control room. The original nested CLI remains available for scripts and advanced operations:
ironrun env init dev
ironrun env set dev HYDRA_DB_API_KEY
ironrun env create staging
ironrun env clone dev staging
ironrun env use staging
ironrun env status
ironrun run hydra-bootstrap
Temporary session sets expire automatically (24 hours by default):
ironrun env create session --temporary --ttl 8h
ironrun env use session
ironrun env prune
Use ironrun run --set staging for a one-run override. env list, env rotate, env delete, env remove, env doctor, and env import cover the remaining lifecycle. Imports accept owner-only dotenv files, display key names but never values, and refuse project-local or group/other-readable files. env export writes only a KEY= template; it never exports plaintext values.
Project metadata lives under .ironrun/ and contains no secret values. The encrypted vault lives outside the repository under ~/.ironrun/vaults/. Every environment has a rotating data key wrapped by a project root key in the native OS credential manager. Existing per-value credential-manager records migrate into the vault on first successful read, with vault commit before legacy delete.
Terminal control room
Run Ironrun with no arguments in a terminal, or use the explicit command:
ironrun
ironrun tui
The TUI opens on the encrypted workspace: environments, masked environment/file secret names, approved commands, and the actions people need most. Use arrows, Enter, Escape, and Tab; press / for the action palette and ? for help. A detected .env can be reviewed by key name, partially selected, confirmed, and verified after encrypted import. Ironrun never deletes the plaintext source for you and warns while it remains. Requests, leases, and audit state live on secondary tabs. There is no reveal, clipboard-copy, or plaintext-export action.
Encrypted file secrets
File-backed secrets are stored as opaque encrypted bytes and materialized only while an approved command runs. Declare a safe basename and the environment variable that receives its temporary path:
secrets:
service-account:
env: GOOGLE_APPLICATION_CREDENTIALS
kind: file
filename: service-account.json
allow: [integration-test]
commands:
- id: integration-test
argv: [go, test, ./integration/...]
secrets: [service-account]
Choose Add secret file in the TUI. Ironrun rejects symlinks, traversal, unsafe basenames, permissive source files, and duplicate targets. At execution it creates a unique owner-only directory outside the repository, writes the file with owner-only permissions, injects only its path, redacts literal and common encoded forms of the contents, and removes the directory after success, failure, timeout, or cancellation. Validated stale crash remnants are removed on startup.
Temporary plaintext necessarily exists on disk while the child process uses a file secret. Cleanup limits its lifetime but cannot guarantee physical erasure from SSD media. Use short command timeouts and revoke agent leases when access is no longer needed.
Revocable agent leases
Agent leases are opt-in for compatibility. Require them for MCP execution:
version: "1"
provider: passthrough
require_agent_leases: true
An agent calls request_lease with policy command IDs, a reason, and a desired TTL. The command remains blocked until a human approves it:
ironrun access list
ironrun access approve req_abc123...
ironrun access leases
ironrun access revoke lease_abc123...
Leases are bound to the exact MCP server session, environment, command set, and expiry. Restarting the MCP server creates a new session; old leases do not transfer. Revocation is checked before the next run.
Trusted workspace sessions (the fast agent path)
For normal local development, an agent can call request_workspace_access or attempt run_sealed with an argv array. Ironrun shows one request in the global Inbox. Approve it once and the same MCP session can run normal commands for the selected project and environment for two hours:
ironrun trust list
ironrun trust grant req_abc123
ironrun trust pause trust_abc123
ironrun trust extend trust_abc123 --ttl 2h
ironrun trust revoke trust_abc123
Trusted sessions are pinned to the MCP session, project, and environment. A server restart creates a new session; an old grant cannot transfer. The default scope is the current dev environment. staging and prod require a separate explicit grant. Normal development network access is enabled, which means a trusted agent could deliberately exfiltrate a secret through network or file actions. Ironrun protects agent context, logs, and routine output; it is not an OS sandbox for a process you choose to trust.
Secret requests and encrypted chat capsules
The request_secret MCP tool accepts only a declared alias and reason. It has no plaintext value field. Fulfill it directly through the TUI or masked CLI:
ironrun access fulfill req_abc123...
If the workflow specifically requires pasting through chat, encrypt the value before it enters the transcript:
ironrun capsule create req_abc123...
# masked prompt; prints ir1.
Paste only the ir1. ciphertext. The agent passes it to claim_capsule; Ironrun decrypts and stores it locally. Capsules are project-bound, MCP-session-bound, request-bound, expire within ten minutes, and become unusable after the request is fulfilled. A plaintext key already pasted into chat cannot be retroactively removed from model-provider logs and should be rotated.
Local curl API
Start the owner-only Unix-socket API:
ironrun serve
curl --unix-socket .ironrun/ironrun.sock http://localhost/v1/status
curl --unix-socket .ironrun/ironrun.sock \
-H 'Content-Type: application/json' \
-d '{"command_id":"test","environment":"dev"}' \
http://localhost/v1/run
The API exposes status, environment metadata, access requests, leases, revocation, denial, and sealed execution. It refuses unknown JSON fields and has no endpoint accepting plaintext secret values.
Now start your agent (claude, cursor, …). It sees run_sealed and asks for one trusted workspace session before normal development work. It can then
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Generalized-Labs
- Source: Generalized-Labs/ironrun
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.