Use
Agents
Fenzi runs command-line agents. You keep the agent you use today. It runs inside the sandbox instead of directly on your machine, with an API key: signing in with a Claude, ChatGPT or Grok subscription is not supported yet. This is not a setting inside Claude Code, and it is not a setting inside Codex.
Which agents
Runs today means the agent is in the catalog and starts through fenzi run. Next means it is not in the catalog yet. Last run by us is the last time we ran that agent through Fenzi on a real sandbox runtime, and where.
| Agent | Run it | Key from your environment | Status | Last run by us |
|---|---|---|---|---|
| Claude Code | fenzi run claude | ANTHROPIC_API_KEY | Runs today | October 2026, macOS (colima) |
| Codex | fenzi run codex | OPENAI_API_KEY | Runs today | October 2026, macOS (colima) |
| OpenCode | fenzi run opencode | ANTHROPIC_API_KEY | Runs today | October 2026, macOS (colima), with a test key, so no model reply yet |
| Grok | fenzi run grok | XAI_API_KEY | Runs today | October 2026, macOS (colima), with a test key, so no model reply yet |
| Cursor CLI | Not in the catalog | Not decided | Next | Not yet |
| Muse | Not in the catalog | Not decided | Next | Not yet |
Each agent runs from an image built on your machine; see Agent images. Run fenzi agents to see the list your CLI version ships with. On Windows, run it through WSL 2. The steps for a missing runtime are in Troubleshooting.
Cursor CLI is still next. The current CLI exchanges an API key for tokens it stores, and a stored token sits inside the sandbox. That is the login case this catalog does not ship. The desktop app is a separate program, and Fenzi does not sandbox it. Muse has no catalog entry yet.
What supported means
Supported is a stronger word than runs today. We will call an agent supported when all four of these pass on macOS and Linux, through Fenzi, with the agent version pinned in its image. No agent carries that label yet, because the checks have not been run on Linux. The table above shows where each one was last run.
It works. The agent's terminal interface is usable inside the sandbox, and calls to its model succeed.
The key stays hidden. The agent's environment holds a placeholder. The real key never appears inside the sandbox.
Denies work. A write outside the policy fails. A call to an unlisted host is blocked. A raw network socket is blocked.
Approvals work. A blocked call files a request, and after approval the retry goes through without a restart.
CI does not run these four checks. It checks the paths they depend on: every week, and on every change to the catalog, it rebuilds each agent's image for x86 and for Arm and fails if a program the entry names is missing from the image, is a link instead of the real file, cannot be run by the sandbox user, or is built for the other processor. The base image and the agent's package can change what lands in the image, and a moved file is a file the policy no longer matches. See Why the real path matters.
Agent images
Each agent runs from its own image, with the agent, git, and common tools. The first fenzi run builds it on your machine from a Dockerfile we publish. We do not redistribute agent binaries.
fenzi agents build claudeRebuild after you change the pinned version. If an agent's executable changes while a sandbox runs, the sandbox blocks its network calls, because it checks that each program is the one it first saw. Start a new sandbox after an update.
Keys and logins
Use an API key. fenzi key set <agent> stores the key in the gateway on your machine, or the first fenzi run stores it from your environment. The agent sees a placeholder. fenzi key list shows which agents have one.
Subscription logins, such as signing in to Claude with an account instead of a key, are not supported. A login flow writes a token inside the agent's environment, and that token would sit inside the sandbox. Use a key.
What the catalog holds
Each agent has an entry with what the sandbox needs to know about it. Custom entries are not supported. The format is shown so you know what a policy depends on.
name: claude
command: claude
image: fenzi/claude
version: "2.1.288"
binaries: # the real path, not the claude link on PATH
- /usr/local/lib/node_modules/@anthropic-ai/claude-code/bin/claude.exe
model: # the only host the key is added for
- host: api.anthropic.com
port: 443
hosts: # needed to start, read-only, never sent the key
- host: platform.claude.com
port: 443
guide_flag: --append-system-prompt # how the request guide is passed
default_flags: # unless you pass the same flag
--permission-mode: manual
start_note: "Claude may ask whether to use the API key it found. Choose Yes: ..."
key:
env: ANTHROPIC_API_KEY
profile_file: profile.yamlThe sandbox matches programs by their real path, so the entry names the file the claude command points to. Programs the agent starts, such as git or npm, get the agent's rules.
The profile tells OpenShell which hosts the key may be sent to. Ours starts from the upstream Claude Code profile with two changes: it names the real path, and it leaves out the error reporting and analytics hosts that profile also opens. If you want those, add them to fenzi.yaml. Claude Code also checks platform.claude.com on its first start and quits if it cannot reach it, so the entry allows that host read-only, without the key. The entry also turns off Claude Code's optional traffic: update checks, telemetry, and release notes.
default_flags start Claude Code in its manual permission mode, so Claude asks you before each command and the policy decides what the command can reach. In auto mode, Claude's own check can refuse a command before the sandbox sees it. To change it, pass your own after the agent's name, as in fenzi run claude --permission-mode auto. start_note is printed before Claude starts: on its first start in a sandbox, Claude asks whether to use the API key it found, with No marked as recommended. Choose Yes. The value is the sandbox's placeholder, not your key, and with No Claude has no key.
guide_flag is the agent's option for adding to its instructions. Fenzi passes a short guide through it, on the command line, each time it starts the agent. The guide says how to request access through the sandbox's policy API. fenzi run prints a guide line when it does this. Claude Code, Codex, OpenCode, and Grok receive it today. Claude Code, Codex, and Grok get it on the command line, so it is not written into the sandbox. OpenCode takes instructions as a file, so Fenzi writes one inside the sandbox, outside the project copy. The image and your project are not changed. An agent without a guide still runs. The sandbox drafts a request from a blocked call, and the agent does not file one with a reason.
Codex
fenzi run codex starts Codex inside the sandbox on your machine. It is not Codex's own sandbox setting. Codex uses an OpenAI API key from OPENAI_API_KEY. Signing in with ChatGPT is not supported, for the reason under Keys and logins.
The codex command from npm is a small launcher. It starts a native program built for your machine's processor, and that program makes the calls. So the entry names that program's path, one for Arm and one for x86. The profile starts from the upstream OpenAI profile: the key goes to api.openai.com as a bearer header, and nowhere else. Upstream also has a Codex profile. It is for ChatGPT sign-in and opens three more hosts, so we do not use it.
Fenzi passes these settings to Codex on the command line each time it starts it. Each one is described in Codex's configuration reference, for Codex 0.160.1, the pinned version.
| Setting | Why |
|---|---|
A model provider with env_key = "OPENAI_API_KEY" | Codex's built-in provider ignores the variable unless codex login stored the key. This one sends it as the header the sandbox fills in. |
sandbox_mode = "danger-full-access" | Codex's own sandbox has to create Linux namespaces, and it cannot do that inside this sandbox, so every command it ran would fail. The sandbox's file, process, and network rules still apply to every command Codex runs. Codex's warning for this mode is hidden, because it says Codex can change your whole computer, which is not the case here. |
web_search = "cached" | Codex's usual default. The mode above would otherwise switch it to live search. |
developer_instructions | The request guide. Codex has no flag for it, so it goes in as this setting. |
| Update check, analytics, feedback, plugins, and connectors off | Optional traffic. Left on, every start fetches Codex's plugin catalog from GitHub and calls chatgpt.com. |
--no-daemon | A sandbox runs one session, so Codex's shared background server has nothing to share. Without it, Codex shows a warning on every start. |
Everything after the agent's name goes to Codex. To run it without the interactive screen, use fenzi run codex exec --skip-git-repo-check "your task". Codex needs the flag because the project is copied in without its .git folder.
One call is still made. Each time the interactive screen opens, it asks raw.githubusercontent.com for an announcement. The sandbox refuses it, the log shows it as denied, and fenzi requests lists a request for it. Deny it or leave it. Codex works without it, and codex exec does not make the call.
Whether Codex files its own request after a refusal, or moves on, depends on the model it runs. The sandbox's own drafts are listed either way.
OpenCode
fenzi run opencode starts OpenCode inside the sandbox on your machine. This catalog entry uses an Anthropic API key from ANTHROPIC_API_KEY, the same variable Claude Code uses. The two keys are stored separately. The key goes only to api.anthropic.com. A project file that selects another provider is overridden, because Fenzi's config is applied last.
The opencode command from npm is a native program. Its install copies the build for this machine onto bin/opencode.exe, and that is the path the sandbox matches, on Arm and on x86. OpenShell 0.1.2 ships no OpenCode profile. Ours is a reviewed copy of the upstream Anthropic profile: the key goes to api.anthropic.com in the x-api-key header. Its id is fenzi-opencode, separate from an organization's own Anthropic profile and from Claude Code's.
With the key set and no --model, OpenCode 1.18.34 calls Claude Sonnet 4.6. Fenzi sets these switches and config keys, from the OpenCode source at tag v1.18.34, each time it starts OpenCode.
| Setting | Why |
|---|---|
OPENCODE_DISABLE_AUTOUPDATE | Turns off the update check. The source describes autoupdate: false the same way, and Fenzi sets that too. |
OPENCODE_DISABLE_MODELS_FETCH | Skips the refresh of the model list from models.opencode.ai. |
OPENCODE_DISABLE_LSP_DOWNLOAD | Skips language-server downloads. |
OPENCODE_DISABLE_DEFAULT_PLUGINS | Turns off the default plugins. |
enabled_providers set to Anthropic only, and share set to disabled | The source says a set provider list enables only those providers, and disabled turns sharing off. |
An instructions file at /sandbox/.fenzi/guide.md | The request guide. OpenCode reads instructions from files, so Fenzi writes this one inside the sandbox before the agent starts. It sits outside the project copy, so it is not in the diff. |
OpenCode also tries to install @opencode-ai/plugin into its config folder on startup. That request to registry.npmjs.org was refused: the path contains an encoded slash, and allowing those makes the policy check fail. The image carries a lockfile that makes OpenCode skip the install.
Everything after the agent's name goes to OpenCode. To run it without the interactive screen, use fenzi run opencode run "your task".
Grok
fenzi run grok starts Grok inside the sandbox on your machine. It uses an xAI API key from XAI_API_KEY. Signing in with grok login is not supported, for the reason under Keys and logins.
The grok command from npm is a link to a native program, bin/grok-native, and that is the path the sandbox matches. OpenShell 0.1.2 ships no Grok profile. Ours uses the same credential shape as the upstream OpenAI profile: the key goes to api.x.ai as a bearer header. The docs at docs.x.ai name that host for API-key auth (GROK_XAI_API_BASE_URL, default https://api.x.ai/v1). The browser-login path uses a different host, and this entry does not open it. The profile id is fenzi-grok.
Fenzi sets these from that settings reference, for Grok 1.0.46.
| Setting | Why |
|---|---|
GROK_DISABLE_AUTOUPDATER=1 | Turns off the update check. An update would call x.ai. |
GROK_SANDBOX=off | Grok's own sandbox is off by default. The setting keeps it off. This sandbox's file, process, and network rules still apply. |
| Web fetch, memory, subagents, and crash reports off | Each already defaults off. The entry sets the variables so they stay off. |
--rules | The request guide. The reference describes this flag as extra rules appended to the system prompt. |
Everything after the agent's name goes to Grok. To run it without the interactive screen, use fenzi run grok -p "your task" --output-format plain.
Web search is a known channel
Claude Code's web search does not leave the sandbox. Anthropic runs the search on its side, and the query and results travel inside the normal calls to the model's API. The sandbox allows those calls, so it cannot tell a search from any other prompt, and it cannot block one without blocking the model.
What the sandbox does block is the next step: fetching a result page from inside the sandbox is a connection to a host the policy does not list, and it is refused like any other.
So the words of a search query can leave through Anthropic. If that matters for a project, turn the search tool off in Claude Code's own settings, or in your Anthropic organization's settings. Fenzi leaves it on and does not enforce either setting.
Codex's configuration reference describes its default search the same way: results come from an index OpenAI keeps, without Codex reaching the web. To remove the tool, pass the setting to Codex: fenzi run codex -c web_search="disabled".
Desktop editors
Fenzi does not sandbox desktop editors, including the Cursor app and VS Code. The Cursor CLI is a separate command-line agent, and that is what the table above means. Connecting an editor to a sandbox remotely is possible upstream. Fenzi makes no claim about it.