- New
mcodexlauncher (#500): launches Codex with a cached status line (model, reasoning effort, cwd, active account, quota usage, plan, cache age) printed before startup.mcodex --tmuxruns inside tmux with mouse scrollback;--tmux --live-accountsadds a livecodex-multi-auth listpane;--monitoris monitor-only. - The status line reads local cache/observability/account state and never calls OpenAI on launch; refreshes quota in the background only when stale (default 10 min,
CODEX_MULTI_AUTH_STATUS_QUOTA_REFRESH_INTERVAL_MS), behind a lock. Resolves the per-project pool whenperProjectAccountsis on and Codex CLI sync is off. Toggle withCODEX_MULTI_AUTH_STATUSLINE=0.
- Validated
MCODEX_MONITOR_INTERVAL/MCODEX_TMUX_HISTORY_LIMITas numeric before interpolating intowatch/tmux commands (no shell injection). --monitor/--live-accountsfail fast whenwatchis missing instead of spawning a broken pane; status path resolves~correctly on Windows and never blocks the event loop.
- Bound the rotation proxy and local bridge loopback-only with no opt-out, and stopped forwarding inbound credentials (
authorization,x-api-key,cookie,proxy-authorization) upstream; IPv6 loopback normalized for bind + base URL (#499). - Stripped inbound
cookie/proxy-authorizationon both egress paths and bounded the proxy's upstream error-body read (#503).
- SHA-256-verified cached Codex instructions: a tampered or unverified-legacy cache is never fast-path served and never drives a conditional
304(#499). - Validated stored ids before building filesystem paths, quarantining unsafe ids (
../poison) or non-numerictime.created; rejected NUL-byte paths inresolvePath(#499, #503). - Made the account store atomic + self-healing (checksummed WAL + temp-and-rename) and retried the transient-lock taxonomy (EBUSY/EPERM/ENOTEMPTY/EACCES/EAGAIN) across all writes (#499).
- Persisted
runtime-observability.jsonowner-only (0o600/ dir0o700) on POSIX; removedAtomics.waitsleeps from the config-load and logger retry paths (#499, #503).
- Detected an unsupported Codex model from the upstream error
detailshape (not just the nestederrorenvelope), surfacing a friendly "Codex unavailable" note acrossbest/forecast/report/live-check instead of leaking raw upstream text (#501/#502). - Kept a genuine transient failure surfacing as the real error, not masked behind the friendly note (#501/#502).
- Bounded prompt and release-metadata fetches by connect+body timeouts that cancel a stalled body (#499).
status/listgained--jsonwith a stable shape whether or not accounts are configured (#499).
- Required a strict integer for
switch <index>(no silent float truncation) (#503). - Masked tokens/emails across log, debug-bundle, and status sinks; the debug bundle redacts the home prefix (Windows case/separator-insensitive), strips config credentials, and masks the account id (#499).
- Bumped
vitestto^4.1.8(dev-only) to clear GHSA-5xrq-8626-4rwp (#503).