Apps and tools
The environment file, and which tools read it
One file holds your API keys, every tool on the machine reads it, and changing it needs a restart.
There is exactly one place for an API key on the machine: ~/.vmbox/env in your home directory. It is created empty when the machine is built, owned by your account and readable only by it, and from that point it belongs to you — nothing on the machine ever rewrites it.
The format is NAME=value, one per line. It is systemd's environment-file syntax, which matters for one reason covered below.
ANTHROPIC_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-...
GEMINI_API_KEY=...Why there is one file
Every tool on the machine runs as the same account with the same home directory, which is what makes signing in once true without any machinery. Dotfiles cover most of it — Claude Code in a terminal tab, the same agent inside the editor, OpenCode in a tab and OpenCode Web all read the same files under your home. A key is the thing a dotfile does not cover, so it has one place instead of six.
One file means one blast radius. Every tool you run as your account can read every key in it. This is not per-tool isolation and it is not a secret manager: it is one file with your keys in it, behind the machine's single login and the file's own permissions.
Where each tool picks it up
Two mechanisms. Knowing which one applies to what you are running is the difference between a key working and a key appearing to be ignored.
- **Services.** Every tool the machine runs as your account has this file named in its systemd unit — the editor and therefore its extensions, Terminal+, the Quick shell, the File manager, OpenCode Web, CodeNomad, n8n, OpenClaw, Hermes, and every app you register yourself. A unit reads the file **when it starts**.
- **Shells.** Your login profile sources the file with
set -afrom both.bashrcand.profile, so a new shell exports every variable in it and anything you launch from that shell inherits them. This is what covers an SSH login.
Changing a key
A new shell sees the change at once. A running service does not, and **nothing on the machine watches this file** — there is no reload. So after changing a key a tool uses, restart that tool.
- Edit
~/.vmbox/env. A terminal tab reaches it; so do the editor and the File manager, both of which open at your home directory rather than inside~/projects. - New terminal tabs have the new value immediately. Tabs you already had open do not — open a new one.
- Restart any running tool that needs it, from its row on the **Apps** card, or with Restart in that row's gear.
The sharp edge: opening a coding CLI as a **Terminal+ tab** from the dashboard does not start a shell — it runs the program directly inside the terminal session, so it inherits the environment that session started with. Add a key, press the button for that CLI, and it may not see the key. Restart Terminal+ from the Apps card, or start the CLI yourself inside a plain shell tab, which does read the profile.
What never reads it
- **Any process that is already running.** That is the whole of the section above, and it is the common case.
- **A shell you already have open.**
- **A Docker container.** Nothing injects it. Pass what a container needs yourself —
--env-file ~/.vmbox/env, or explicit-eflags. - **Anything running as another account**, including the machine software itself. That is deliberate: a file your account can write must not be able to set the environment of anything privileged.
- **Commands the machine runs for you** — installs, repairs, and the dashboard's own terminal actions. Those get a fixed, minimal environment, so a key here never reaches them.
Two ways to get it wrong
**export NAME=value is not the syntax.** The shell half tolerates it. systemd does not: it would create a variable whose name is literally export NAME. So the key reaches your terminals and silently never reaches a service, which looks like the service ignoring it. Leave export off.
**Some names are reserved, and setting them breaks things.** This file is loaded *over* a unit's own settings, which is what makes it work at all — so HOME, PATH, USER, LOGNAME, SHELL, PWD, LANG, TERM, PORT, NPM_CONFIG_PREFIX, VMBOX_WORKSPACE and the three ZELLIJ_ names must not appear in it.
PORT has the most surprising effect: every app you register is told its port that way, so setting PORT here moves all of them off the port their address points at. The machine does notice — the component that owns this file reports itself degraded and names the offending key — but it notices after the fact, not when you save.
What the dashboard shows about it
Deliberately very little. There is no editor and no key list anywhere on the dashboard, because such a page would put your keys on a screen. The **Sign-ins** card checks whether a known key *name* is present and prints, for example, login in ANTHROPIC_API_KEY in ~/.vmbox/env. It never reads a value and never calls a vendor, so it can report a key as present and be wrong about it working.
There is also no vmbox env command. A text editor is the only writer this file will ever have. And the file is never part of what the machine reports to us — see trust and security for the whole of what is in a report.
Wrong, out of date, or missing the case you have? Tell us. A page that describes the machine incorrectly is a fault, not a typo.