## Why
`rust-release` now publishes `codex-package-<target>.tar.gz` as the
canonical native package payload. npm staging should consume those
archives directly instead of keeping legacy synthesis code that fetched
`rg`, copied standalone binaries, and rebuilt an approximate package
layout.
That also means the package builder should not know the internal shape
of `codex-package`. It should extract and copy the target payload
wholesale so future layout changes stay localized to the archive
producer.
The release job stages `codex`, `codex-responses-api-proxy`, and
`codex-sdk` together, so native artifact download should be filtered,
observable, and shared across component installs. Since that native
hydration is now only used by release staging, keeping a separate
`install_native_deps.py` CLI adds an extra wrapper without a real
caller.
## What Changed
- Removed legacy `codex-package` synthesis and related compatibility
flags from npm staging.
- Folded the remaining native artifact hydration code into
`scripts/stage_npm_packages.py` and deleted
`codex-cli/scripts/install_native_deps.py`.
- Made platform package staging copy the full extracted target directory
instead of enumerating package entries.
- Kept non-`codex-package` native components under their component
directory name instead of using a legacy destination map.
- Split native staging by component set while sharing one
workflow-artifact cache across the invocation.
- Changed workflow artifact download to select target artifacts by name,
print sizes/progress, and reuse cached artifacts.
- Removed the implicit `CI=true` default from `build_npm_package.py`;
local CI-shaped runs should set that environment explicitly.
- Kept `npm pack` cache/log output in its temporary directory so packing
does not write to the user npm cache.
## Verification
- `python3 -m py_compile scripts/stage_npm_packages.py
codex-cli/scripts/build_npm_package.py`
- `python3 -m unittest discover -s scripts/codex_package -p "test_*.py"`
- `scripts/stage_npm_packages.py --help`
- `codex-cli/scripts/build_npm_package.py --help`
- Ran the release-shaped staging command from `rust-release.yml` against
workflow run https://github.com/openai/codex/actions/runs/26240748758
with `CI=true` set locally to match GitHub Actions:
```sh
CI=true python3 ./scripts/stage_npm_packages.py \
--release-version 0.133.0 \
--workflow-url https://github.com/openai/codex/actions/runs/26240748758 \
--package codex \
--package codex-responses-api-proxy \
--package codex-sdk
```
That completed successfully, downloaded only the six target artifacts
once, reused the cache for `codex-responses-api-proxy`, and produced all
nine npm tarballs. Generated tarballs and staging/artifact temp dirs
were cleaned afterward.
## Why
Installing `@openai/codex` currently places a Dotslash `rg` manifest at
`node_modules/@openai/codex/bin/rg`, even though the native optional
dependency already ships the actual helper under
`vendor/<target>/codex-path/rg`. The launcher prepends that `codex-path`
directory, so the top-level `bin/rg` file is redundant in the npm
install.
The remaining direct consumers of the manifest are package-building
paths: `scripts/codex_package/ripgrep.py` and
`codex-cli/scripts/install_native_deps.py`. Keeping the manifest under
`codex-cli/bin` makes it look like a shipped npm binary, so this moves
it next to the package-builder code that owns it. The checked-in
`@openai/codex` package metadata should likewise describe only the meta
package payload; generated platform packages continue to publish
`vendor`.
## What Changed
- Moved the Dotslash ripgrep manifest from `codex-cli/bin/rg` to
`scripts/codex_package/rg`.
- Updated the package builder, npm native-artifact hydrator, README, and
CLI help text to reference the new manifest location.
- Stopped `codex-cli/scripts/build_npm_package.py` from copying `rg`
into the `@openai/codex` meta package.
- Narrowed the checked-in meta package `files` whitelist to
`bin/codex.js`.
## Verification
- `python3 -m unittest discover -s scripts/codex_package -p "test_*.py"`
- `python3 -m unittest discover -s codex-cli/scripts -p "test_*.py"`
- `python3 -m py_compile codex-cli/scripts/build_npm_package.py
codex-cli/scripts/install_native_deps.py
scripts/codex_package/ripgrep.py scripts/codex_package/cli.py
scripts/stage_npm_packages.py`
- `codex-cli/scripts/build_npm_package.py --package codex --version
0.0.0-test --pack-output <tmp>/codex-meta-no-vendor.tgz`
- `tar -tf <tmp>/codex-meta-no-vendor.tgz` showed only
`package/bin/codex.js`, `package/package.json`, and `package/README.md`.
- Direct staging check showed `codex` uses `files: ["bin/codex.js"]`
while `codex-darwin-arm64` still uses `files: ["vendor"]`.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/23833).
* #23836
* __->__ #23833
## Summary
The npm platform packages should stop carrying a bespoke native layout
now that the release workflow builds canonical Codex package archives.
Keeping npm on the same `bin/`, `codex-resources/`, and `codex-path/`
structure lets the Rust package-layout detection behave consistently
across standalone, npm, and future DotSlash installs.
This changes platform npm packages to stage the `codex-package` artifact
for each target under `vendor/<target>`. The Node launcher now resolves
`bin/codex` and prepends `codex-path`, while retaining legacy
`vendor/<target>/codex` and `vendor/<target>/path` fallback support for
local development and migration. The npm staging helper downloads
`codex-package` archives instead of rebuilding the CLI payload from
individual `codex`, `rg`, `bwrap`, and sandbox helper artifacts.
CI still needs to stage npm packages from historical rust-release
workflow artifacts that predate package archives, so the staging scripts
expose an explicit `--allow-legacy-codex-package` fallback. That
fallback synthesizes the canonical package layout from legacy per-binary
artifacts and is wired only into the CI smoke path; release staging
remains strict and continues to require real package archives.
For direct local use, `install_native_deps.py` now points its built-in
default workflow at the same recent artifact run used by CI and
automatically enables legacy package synthesis only when
`--workflow-url` is omitted. Explicit workflow URLs remain strict unless
callers opt in with `--allow-legacy-codex-package`.
## Test plan
- `python3 -m py_compile codex-cli/scripts/build_npm_package.py
codex-cli/scripts/install_native_deps.py scripts/stage_npm_packages.py
scripts/codex_package/cli.py`
- `node --check codex-cli/bin/codex.js`
- `ruby -e 'require "yaml";
YAML.load_file(".github/workflows/rust-release.yml");
YAML.load_file(".github/workflows/ci.yml"); puts "ok"'`
- Staged a synthetic `codex-linux-x64` platform package from a canonical
vendor tree and verified it copied only `bin/`, `codex-path/`,
`codex-resources/`, and `codex-package.json`.
- Imported `install_native_deps.py` and extracted a synthetic
`codex-package-x86_64-unknown-linux-musl.tar.gz` into `vendor/<target>`.
- Ran legacy-layout conversion smokes for Linux, Windows, and unsigned
macOS artifact naming.
- Ran a synthetic `install_native_deps.py` default-workflow smoke that
verifies legacy package synthesis is automatic only when
`--workflow-url` is omitted.
- `NPM_CONFIG_CACHE="$tmp_dir/npm-cache" python3
./scripts/stage_npm_packages.py --release-version 0.125.0 --workflow-url
https://github.com/openai/codex/actions/runs/26131514935 --package codex
--allow-legacy-codex-package --output-dir "$tmp_dir"`
- `node codex-cli/bin/codex.js --version`
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/23637).
* #23638
* __->__ #23637
## Why
Users and support need a single command that captures the local Codex
runtime, configuration, auth, terminal, network, and state shape without
asking the user to know which diagnostic depth to choose first. `codex
doctor` now runs the useful checks by default and makes the detailed
human output the default because the command is usually run when someone
already needs context.
The command also targets concrete support failure modes we have seen
while iterating on the design:
- update-target mismatches like #21956, where the installed package
manager target can differ from the running executable
- terminal and multiplexer issues that depend on `TERM`, tmux/zellij
state, color handling, and TTY metadata
- provider-specific HTTP/WebSocket connectivity, including ChatGPT
WebSocket handshakes and API-key/provider endpoint reachability
- local state/log SQLite integrity problems and large rollout
directories
- feedback reports that need an attached, redacted diagnostic snapshot
without asking the user to run a second command
## What Changed
- Adds `codex doctor` as a grouped CLI diagnostic report with default
detailed output and `--summary` for the compact view.
- Adds stable report sections for Environment, Configuration, Updates,
Connectivity, and Background Server, plus a top Notes block that
promotes anomalies such as available updates, large rollout directories,
optional MCP issues, and mixed auth signals.
- Adds runtime provenance, install consistency, bundled/system search
readiness, terminal/multiplexer metadata, `config.toml` parse status,
auth mode details, sandbox details, feature flag summaries, update
cache/latest-version state, app-server daemon state, SQLite integrity
checks, rollout statistics, and provider-aware network diagnostics.
- Adds ChatGPT WebSocket diagnostics that report the negotiated HTTP
upgrade as `HTTP 101 Switching Protocols` and include timeout, DNS,
auth, and provider context in detailed output.
- Makes reachability provider-aware: API-key OpenAI setups check the API
endpoint, ChatGPT auth checks the ChatGPT path, and custom/AWS/local
providers check configured HTTP endpoints when available.
- Adds structured, redacted JSON output where `checks` is keyed by check
id and `details` is a key/value object for support tooling.
- Integrates doctor with feedback uploads by attaching a best-effort
`codex-doctor-report.json` report and adding derived Sentry tags for
overall status and failing/warning checks.
- Updates the TUI feedback consent copy so users can see that the doctor
report is included when logs/diagnostics are uploaded.
- Updates the CLI bug issue template to ask reporters for `codex doctor
--json` and render pasted reports as JSON.
## Example Output
The examples below are sanitized from local smoke runs with `--no-color`
so the structure is reviewable in plain text.
### `codex doctor`
```text
Codex Doctor v0.0.0 · macos-aarch64
Notes
↑ updates 0.130.0 available (current 0.0.0, dismissed 0.128.0)
⚠rollouts 1,526 active files · 2.53 GB on disk
âš mcp MCP configuration has optional issues
âš auth mixed auth signals: ChatGPT login plus API key env var; HTTP reachability uses API-key mode
─────────────────────────────────────────────────────────────
Environment
✓ runtime local debug build
version 0.0.0
install method other
commit unknown
executable ~/code/codex.fcoury-doct…x-rs/target/debug/codex
✓ install consistent
context other
managed by npm: no · bun: no · package root —
PATH entries (2) ~/.local/share/mise/installs/node/24/bin/codex
~/.local/share/mise/shims/codex
✓ search ripgrep 15.1.0 (system, `rg`)
✓ terminal Ghostty 1.3.2-main-+b0f827665 · tmux 3.6a · TERM=xterm-256color
terminal Ghostty
TERM_PROGRAM ghostty
terminal version 1.3.2-main-+b0f827665
TERM xterm-256color
multiplexer tmux 3.6a
tmux extended-keys on
tmux allow-passthrough on
tmux set-clipboard on
✓ state databases healthy
CODEX_HOME ~/.codex (dir)
state DB ~/.codex/state_5.sqlite (file) · integrity ok
log DB ~/.codex/logs_2.sqlite (file) · integrity ok
active rollouts 1,526 files · 2.53 GB (avg 1.70 MB)
archived rollouts 8 files · 3.84 MB (avg 491.11 KB)
Configuration
✓ config loaded
model gpt-5.5 · openai
cwd ~/code/codex.fcoury-doctor/codex-rs
config.toml ~/.codex/config.toml
config.toml parse ok
MCP servers 1
feature flags 36 enabled · 7 overridden (full list with --all)
overrides code_mode, code_mode_only, memories, chronicle, goals, remote_control, prevent_idle_sleep
✓ auth auth is configured
auth storage mode File
auth file ~/.codex/auth.json
auth env vars present OPENAI_API_KEY
stored auth mode chatgpt
stored API key false
stored ChatGPT tokens true
stored agent identity false
⚠mcp MCP configuration has optional issues — Set the missing MCP env vars or disable the affected server.
configured servers 1
disabled servers 0
streamable_http servers 1
optional reachability openaiDeveloperDocs: https://developers.openai.com/mcp (HEAD connect failed; GET connect failed)
✓ sandbox restricted fs + restricted network · approval OnRequest
approval policy OnRequest
filesystem sandbox restricted
network sandbox restricted
Connectivity
✓ network network-related environment looks readable
✓ websocket connected (HTTP 101 Switching Protocols) · 15s timeout
model provider openai
provider name OpenAI
wire API responses
supports websockets true
connect timeout 15000 ms
auth mode chatgpt
endpoint wss://chatgpt.com/backend-api/<redacted>
DNS 2 IPv4, 2 IPv6, first IPv6
handshake result HTTP 101 Switching Protocols
✗ reachability one or more required provider endpoints are unreachable over HTTP — Check proxy, VPN, firewall, DNS, and custom CA configuration.
reachability mode API key auth
openai API https://api.openai.com/v1 connect failed (required)
Background Server
â—‹ app-server not running (ephemeral mode)
─────────────────────────────────────────────────────────────
11 ok · 1 idle · 4 notes · 1 warn · 1 fail failed
--summary compact output --all expand truncated lists
--json redacted report
```
### `codex doctor --summary`
```text
Codex Doctor v0.0.0 · macos-aarch64
Notes
↑ updates 0.130.0 available (current 0.0.0, dismissed 0.128.0)
⚠rollouts 1,526 active files · 2.53 GB on disk
âš mcp MCP configuration has optional issues
âš auth mixed auth signals: ChatGPT login plus API key env var; HTTP reachability uses API-key mode
─────────────────────────────────────────────────────────────
Environment
✓ runtime local debug build
✓ install consistent
✓ search ripgrep 15.1.0 (system, `rg`)
✓ terminal Ghostty 1.3.2-main-+b0f827665 · tmux 3.6a · TERM=xterm-256color
✓ state databases healthy
Configuration
✓ config loaded
✓ auth auth is configured
⚠mcp MCP configuration has optional issues — Set the missing MCP env vars or disable the affected server.
✓ sandbox restricted fs + restricted network · approval OnRequest
Updates
✓ updates update configuration is locally consistent
Connectivity
✓ network network-related environment looks readable
✓ websocket connected (HTTP 101 Switching Protocols) · 15s timeout
✗ reachability one or more required provider endpoints are unreachable over HTTP — Check proxy, VPN, firewall, DNS, and custom CA configuration.
Background Server
â—‹ app-server not running (ephemeral mode)
─────────────────────────────────────────────────────────────
11 ok · 1 idle · 4 notes · 1 warn · 1 fail failed
Run codex doctor without --summary for detailed diagnostics.
--all expand truncated lists --json redacted report
```
### `codex doctor --json` shape
```json
{
"schema_version": 1,
"overall_status": "fail",
"checks": {
"runtime.provenance": {
"id": "runtime.provenance",
"category": "Environment",
"status": "ok",
"summary": "local debug build",
"details": {
"version": "0.0.0",
"install method": "other",
"commit": "unknown"
}
},
"sandbox.helpers": {
"id": "sandbox.helpers",
"category": "Configuration",
"status": "ok",
"summary": "restricted fs + restricted network · approval OnRequest",
"details": {
"approval policy": "OnRequest",
"filesystem sandbox": "restricted",
"network sandbox": "restricted"
}
}
}
}
```
### `/feedback` new sentry attachment
<img width="938" height="798" alt="CleanShot 2026-05-13 at 15 36 14"
src="https://github.com/user-attachments/assets/715e62e0-d7b4-4fea-a35a-fd5d5d33c4c0"
/>
### New section in CLI issue template
<img width="1164" height="435" alt="CleanShot 2026-05-13 at 15 47 24"
src="https://github.com/user-attachments/assets/9081dc25-a28c-4afa-8ba1-e299c2b4031d"
/>
## How to Test
1. Run `cargo run --bin codex -- doctor --no-color`.
2. Confirm the detailed report is the default and includes promoted
Notes, grouped sections, terminal details, state DB integrity, rollout
stats, provider reachability, WebSocket diagnostics, and app-server
status.
3. Run `cargo run --bin codex -- doctor --summary --no-color`.
4. Confirm the compact view keeps the same sections and summary counts
but omits detailed key/value rows.
5. Run `cargo run --bin codex -- doctor --json`.
6. Confirm the output is redacted JSON, `checks` is an object keyed by
check id, and each check's `details` is a key/value object.
7. Preview the CLI bug issue template and confirm the `Codex doctor
report` field appears after the terminal field, asks for `codex doctor
--json`, and renders pasted output as JSON.
8. Start a feedback flow that includes logs.
9. Confirm the upload consent copy lists `codex-doctor-report.json`
alongside the log attachments.
Targeted tests:
- `cargo test -p codex-cli doctor`
- `cargo test -p codex-app-server
doctor_report_tags_summarize_status_counts`
- `cargo test -p codex-feedback`
- `cargo test -p codex-tui feedback_view`
- `just argument-comment-lint`
- `git diff --check`
## Summary
Starts the process of getting rid of `--full-auto`, with some
concessions:
1. Fully removes the command from the tui, since it just resolves to the
default permissions there, and encourages users to use the one-time
trust flow if they're not in a trusted repo.
2. Marks the command as deprecated in `codex exec`, in case users are
actively relying on this. We'll remove in an upcoming n+X release.
3. Cleans up some of the `codex sandbox` cli logic, to keep supporting
legacy sandbox policies for now.
This isn't the cleanest setup, but I think it is worthwhile to warn
users for one release before hard-removing it.
## Testing
- [x] Updated unit tests
## Summary
This PR hardens package-manager usage across the repo to reduce
dependency supply-chain risk. It also removes the stale `codex-cli`
Docker path, which was already broken on `main`, instead of keeping a
bitrotted container workflow alive.
## What changed
- Updated pnpm package manager pins and workspace install settings.
- Removed stale `codex-cli` Docker assets instead of trying to keep a
broken local container path alive.
- Added uv settings and lockfiles for the Python SDK packages.
- Updated Python SDK setup docs to use `uv sync`.
## Why
This is primarily a security hardening change. It reduces
package-install and supply-chain risk by ensuring dependency installs go
through pinned package managers, committed lockfiles, release-age
settings, and reviewed build-script controls.
For `codex-cli`, the right follow-up was to remove the local Docker path
rather than keep patching it:
- `codex-cli/Dockerfile` installed `codex.tgz` with `npm install -g`,
which bypassed the repo lockfile and age-gated pnpm settings.
- The local `codex-cli/scripts/build_container.sh` helper was already
broken on `main`: it called `pnpm run build`, but
`codex-cli/package.json` does not define a `build` script.
- The container path itself had bitrotted enough that keeping it would
require extra packaging-specific behavior that was not otherwise needed
by the repo.
## Gaps addressed
- Global npm installs bypassed the repo lockfile in Docker and CLI
reinstall paths, including `codex-cli/Dockerfile` and
`codex-cli/bin/codex.js`.
- CI and Docker pnpm installs used `--frozen-lockfile`, but the repo was
missing stricter pnpm workspace settings for dependency build scripts.
- Python SDK projects had `pyproject.toml` metadata but no committed
`uv.lock` coverage or uv age/index settings in `sdk/python` and
`sdk/python-runtime`.
- The secure devcontainer install path used npm/global install behavior
without a local locked package-manager boundary.
- The local `codex-cli` Docker helper was already broken on `main`, so
this PR removes that stale Docker path instead of preserving a broken
surface.
- pnpm was already pinned, but not to the current repo-wide pnpm version
target.
## Verification
- `pnpm install --frozen-lockfile`
- `.devcontainer/codex-install`: `pnpm install --prod --frozen-lockfile`
- `.devcontainer/codex-install`: `./node_modules/.bin/codex --version`
- `sdk/python`: `uv lock --check`, `uv sync --locked --all-extras
--dry-run`, `uv build`
- `sdk/python-runtime`: `uv lock --check`, `uv sync --locked --dry-run`,
`uv build --wheel`
- `pnpm -r --filter ./sdk/typescript run build`
- `pnpm -r --filter ./sdk/typescript run lint`
- `pnpm -r --filter ./sdk/typescript run test`
- `node --check codex-cli/bin/codex.js`
- `docker build -f .devcontainer/Dockerfile.secure -t codex-secure-test
.`
- `cargo build -p codex-cli`
- repo-wide package-manager audit
Problem: codex-cli/README.md is obsolete and confusing to keep around.
Solution: Delete codex-cli/README.md so the stale README is no longer
present in the repository.
- hanzo-tunnel v0.1.0 published to crates.io (was path dep to ../../../tunnel)
- cli: tunnel + tunnel-bridge deps now optional behind `tunnel` feature flag
- cli: cloud module (ZT + relay) gated with #[cfg(feature = "tunnel")]
- tunnel-bridge: all hanzo_tunnel usage gated behind `tunnel` feature
- CI: fix prettier by scoping JS globs, excluding symlinked CLAUDE.md
- CI: format all workflows and docs with prettier
- Workspace compiles clean without tunnel feature (CI default)
- Local builds with `--features tunnel` still work with crates.io dep