Files
msd-core/docs/how-to/control-the-reported-host-runtime.md
Jakub Zych a9a7a328e6 refactor: hard-fork GSD -> MSD (Make Software Done)
Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD
across contents and paths, upstream package/repo coordinates -> @golem15/msd-core
and golem15com/msd-core. Deep links into upstream history, sibling upstream
packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is.

Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line,
package/plugin identity, regenerated lockfile, install-tree fixtures, derived
registries and benchmark baseline; migration checksum baseline re-locked
(MSD keeps its own install state, so no install had applied the old sums);
sort-order and regex-escaped expectations in tests adjusted.
2026-10-06 01:47:40 +02:00

4.8 KiB

How to control which host runtime MSD reports

Goal: Make agent_runtime — the runtime MSD reports it is running under, and the one it checks for installed agents — say what you actually want, and know why it says what it says.

Prerequisites: A project with a .planning/ directory. Read the current answer with:

node msd-tools.cjs init plan-phase 1 --raw

The JSON carries agent_runtime, plus the agents_dir / agents_installed / missing_agents triple derived from it. For the config key itself, see runtime.


The ladder, in order

MSD answers "which runtime am I?" from the first of these that produces a value:

# Source Set it by Wins over
1 MSD_RUNTIME environment variable MSD_RUNTIME=opencode in the environment everything below
2 runtime in .planning/config.json "runtime": "codex" detection and the default
3 Host detection (added in v1.11) nothing — it is automatic the default only
4 Default — — (claude)

Rungs 1 and 2 are explicit — you stated an intent, and MSD does not second-guess it. Rung 3 only ever runs when both are unset. This is what preserves the behavior of every existing config: if you have ever set runtime, nothing about your setup changes.


What detection actually looks at

Detection answers a narrow question — is this process running inside a Codex session? — and only from signals Codex itself documents.

Signal Where it comes from Why it is trusted
CODEX_SANDBOX is set and non-empty Codex injects it into child processes it spawns via Seatbelt Documented in Codex's own AGENTS.md; present in exactly the processes Codex runs, which is where MSD runs
CODEX_SANDBOX_NETWORK_DISABLED is set and non-empty Codex injects it when running the shell tool with the network sandbox on same source
CODEX_HOME is set and $CODEX_HOME/config.toml exists you exported it Exporting CODEX_HOME is you designating a Codex state root; the config.toml check confirms the directory is a real one

Anything else — no signal — means no detection, and rung 4 applies.


The two questions this page exists for

"I'm in a Codex session and it still says claude"

Work down the ladder:

Check What to do
Is MSD_RUNTIME set to something else? echo $MSD_RUNTIME — it outranks everything. Unset it, or set it to codex.
Does .planning/config.json have a runtime? An explicit "runtime": "claude" wins over detection, by design. Change it or remove the key.
Is your Codex sandbox off? With sandbox_mode = "danger-full-access", Codex sets neither sandbox variable, so there is nothing for MSD to detect. This is the most common cause.
Still nothing? Set it explicitly. Detection is a convenience, not a contract — "runtime": "codex" in .planning/config.json is the supported, permanent answer.

Detection is deliberately conservative: when it cannot tell, it reports the old default rather than guessing. A wrong agent_runtime sends MSD looking for agents in the wrong directory, so silence is the safer failure.

"It says codex and I am not using Codex"

One cause, and it is benign:

CODEX_HOME is exported in your shell profile, and $CODEX_HOME/config.toml exists.

MSD treats an explicitly-exported CODEX_HOME as you designating a Codex root. If you keep it exported globally but work in another runtime, pin the runtime for that project:

{ "runtime": "claude" }

in .planning/config.json. Rung 2 outranks detection, so this settles it permanently.

Note what is not a cause: simply having Codex installed. MSD never probes the default ~/.codex/config.toml. That file exists on every machine that has ever run Codex, so treating it as a signal would misreport every other runtime's sessions — which is precisely why the check requires you to have exported CODEX_HOME yourself.


What this does not change

Detection moves the reported runtime and the agent-installation check that hangs off it. It deliberately does not touch:

  • Model resolution. Runtime-aware tier resolution still reads the explicit runtime config key only. A detected-Codex session does not gain or lose model pins — see Runtime-aware profiles and ADR-2313.
  • Slash-command style. MSD still emits /msd-<cmd> unless the runtime was set explicitly; a detected-Codex session does not switch to the $msd-<cmd> shell-var form. Set runtime explicitly if you want that.
  • Any file. Detection reads environment variables and checks for one file's existence. It never writes ~/.msd/defaults.json, never edits .planning/config.json, and never shells out.