Skip to content

Fix Termux/Android compatibility issues (DNS, locking, Android target support)#5

Draft
wallentx wants to merge 354 commits intomainfrom
wallentx/termux-target
Draft

Fix Termux/Android compatibility issues (DNS, locking, Android target support)#5
wallentx wants to merge 354 commits intomainfrom
wallentx/termux-target

Conversation

@wallentx
Copy link
Copy Markdown
Owner

@wallentx wallentx commented Feb 14, 2026

Codex CLI currently fails on native Termux/Android due to DNS resolution and unsupported lock semantics in this environment. This PR adds compatibility adjustments that allow:

  • Authentication and request execution to succeed on Termux/Android.
  • Lock-based session persistence to work without runtime errors.
  • Reproducible Android build artifacts in CI for easier validation and testing.

The changes preserve existing behavior on non-Android platforms.


Changes

DNS/Resolver fixes

  • Apply Android/Termux-specific resolver fallback path while preserving normal resolver behavior elsewhere.
  • Fallback chain for resolver config:
    1. system config,
    2. $PREFIX/etc/resolv.conf,
    3. a deterministic fallback.
  • Register both UDP and TCP entries for nameservers.
  • Add tests covering parsing, protocol registration, and environment detection.

Graceful handling of unsupported locks

  • Detect and handle std::io::ErrorKind::Unsupported from try_lock() without failing.
  • Allow session preference flows (e.g., “press p” to auto-accept) to proceed when locks are unavailable.
  • Adjust affected unit tests to consider environments without file-locking support.

Android build target support in CI

To produce and validate builds targeting Android (e.g. native Termux):

  • Add aarch64-linux-android target in GitHub Actions.
  • Install and configure Android NDK in CI workflow.
  • Configure Cargo linker, CC, and AR for the Android target.
  • Enable vendored OpenSSL for Android builds.
  • Adjust keyring target dependencies for Android.

This enables CI to build Android artifacts that include the compatibility adjustments above, which aids testing and validation.


Validation

  • just fmt
  • cargo test
  • Verified on a real native Termux/Android device (no proot/chroot):
    • Authentication succeeds.
    • Interactive requests complete.
    • Session preference persistence works.
    • No regressions observed on existing targets.

@wallentx wallentx changed the title Wallentx/termux target Fix Termux/Android compatibility issues (DNS, locking, Android target support) Feb 14, 2026
@wallentx wallentx force-pushed the wallentx/termux-target branch from d61ca4b to 6c3d14b Compare February 15, 2026 16:17
@robertkirkman
Copy link
Copy Markdown

robertkirkman commented Feb 19, 2026

Hi, do you know if this will continue to work with, and maybe improve, https://github.com/termux-user-repository/tur/blob/cf26feef42820d03b7061866ee5f456324657a7a/tur/codex/build.sh ?

@wallentx
Copy link
Copy Markdown
Owner Author

Hi, do you know if this will continue to work with, and maybe improve, https://github.com/termux-user-repository/tur/blob/cf26feef42820d03b7061866ee5f456324657a7a/tur/codex/build.sh ?

Screenshot_20260219-225637

AddText_02-20-11 01 35~2

The current TUR provided codex is impacted by the issue that my PR resolves, so if I get an invite to PR upstream, this should fix at least the locking issues.
I'll need to fork TUR and point it here to see what the build produces.

I had some code change logic to handle the absence of /etc/resolve.conf on android, but found that simply adding an aarch64-linux-android target made all of that unnecessary.. but if this never gets merged upstream, I could provide a patch with that original conditional logic so that this can be fully solved via patches in the TUR. Are you a maintainer, @robertkirkman ?

@robertkirkman
Copy link
Copy Markdown

I had some code change logic to handle the absence of /etc/resolve.conf on android, but found that simply adding an aarch64-linux-android target made all of that unnecessary.. but if this never gets merged upstream, I could provide a patch with that original conditional logic so that this can be fully solved via patches in the TUR. Are you a maintainer, @robertkirkman ?

Yes, I have merge permission for TUR. If you want users of Codex on TUR to get this fix, you could also submit this to https://github.com/termux-user-repository/tur/pulls and I would be able to approve it there, and then whenever this version gets merged the patch could be removed from the TUR version when it gets updated.

Comment thread codex-rs/utils/pty/src/pty.rs Outdated
#[cfg(target_os = "android")]
impl portable_pty::PtySystem for AndroidPtySystem {
fn openpty(&self, _size: PtySize) -> anyhow::Result<portable_pty::PtyPair> {
anyhow::bail!("PTY not supported on Android")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you describe what goes wrong if you do not disable PTY on Android? I was wondering about that.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/wallentx/codex/actions/runs/22244673318/job/64355979725#step:22:121

   Compiling codex-cli v0.104.0-dev (/home/runner/work/codex/codex/codex-rs/cli)
error: linking with `/usr/local/lib/android/sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang` failed: exit status: 1
  |
  = note:  "/usr/local/lib/android/sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang" "<1 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "/tmp/rustc4CmmoS/{liblzma_sys-992b66fb89471db7,libbzip2_sys-ee2c4dea6113765e,liblibsqlite3_sys-74e3b2d982fb2832,libtree_sitter_bash-ba13aee0aa28265f,libtree_sitter-1ca4d45594f820fa,libzstd_sys-4dde45f3f9f13c1c,libaws_lc_sys-d9601faf5d845464,libring-7cc72dfc028a344e,libopenssl_sys-829833977529d351}.rlib" "<sysroot>/lib/rustlib/aarch64-linux-android/lib/libcompiler_builtins-*.rlib" "-Wl,-Bdynamic" "-lz" "-ldl" "-llog" "-lunwind" "-ldl" "-lm" "-lc" "-L" "/tmp/rustc4CmmoS/raw-dylibs" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/tree-sitter-6f935e6c94cea3b9/out" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/tree-sitter-bash-7043ce2866a501a9/out" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/aws-lc-sys-f78b418f69a41d9e/out" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/ring-478a869566eb754e/out" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/openssl-sys-50d764c58005cb2d/out/openssl-build/install/lib" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/zstd-sys-8fee5b13a7070f55/out" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/libsqlite3-sys-0c9f47d8c58ecbb3/out" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/bzip2-sys-18f29db9c9b4c5d5/out/lib" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/lzma-sys-e22fad6537c17296/out" "-o" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/deps/codex-94cb809459dd56d4" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-Wl,-O1" "-Wl,--strip-all" "-nodefaultlibs"
  = note: some arguments are omitted. use `--verbose` to show all linker arguments
  = note: ld.lld: error: undefined symbol: openpty
          >>> referenced by codex.5ecef7b0ac420300-cgu.0
          >>>               /home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/deps/codex-94cb809459dd56d4.codex.5ecef7b0ac420300-cgu.0.rcgu.o:(_$LT$portable_pty..unix..UnixPtySystem$u20$as$u20$portable_pty..PtySystem$GT$::openpty::hf566b6e5dd6631e1)
          clang: error: linker command failed with exit code 1 (use -v to see invocation)
          

error: could not compile `codex-cli` (bin "codex") due to 1 previous error

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh I see, thanks for showing that.

The cause of the error ld.lld: error: undefined symbol: openpty is because the openpty function does not exist in Android 5, and this PR code is targeting Android 5.

Termux only supports Android 7 and newer, and in Android 6 and newer the openpty function does exist, so this error will not affect Termux.

Therefore, it is appropriate to keep this code which disables PTY for an upstream Codex version that can be used with Android 5, but for the Termux version the code which disables PTY will be possible to disable.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh thanks for this! I'll bump the API level to 24 and remove the PTY exclusion. I don't suspect this will be useful to anyone outside of termux.

Copy link
Copy Markdown
Owner Author

@wallentx wallentx Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robertkirkman I bumped the API target level to 24 and it failed with the same error.
https://github.com/wallentx/codex/actions/runs/22280259015/job/64449939914
Copilot informs me:

There’s an important difference between Termux and native Android development with the NDK. Termux provides openpty via its own libraries (such as libutil), so code compiled and run in Termux has access to that function. However, when building native Android apps with the NDK, the openpty function is not available in Android’s system libraries (bionic libc)—regardless of Android version. This means native binaries targeting Android, including Android 6 and newer, will encounter linker errors if they rely on openpty, unless they provide their own implementation.

So, while Termux users can use openpty, native Android apps built with the NDK cannot depend on it. That’s why this linker error matters for the CI job and NDK-based builds, even though Termux itself is unaffected.

I'll still keep the target level to 24, since that's what termux-packages uses, but it looks like I need to reapply the pty exclusion for android

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#!/bin/bash

echo "Instalando ca-certificates..."
pkg install ca-certificates -y

echo "Configurando .bashrc..."

Evita duplicados

if ! grep -q "SSL_CERT_FILE" ~/.bashrc; then
echo '' >> ~/.bashrc
echo '# Codex Termux fix' >> ~/.bashrc
echo 'export SSL_CERT_FILE=$PREFIX/etc/tls/cert.pem' >> ~/.bashrc
echo 'export SSL_CERT_DIR=$PREFIX/etc/tls/certs' >> ~/.bashrc
echo 'export RESOLV_CONF=$PREFIX/etc/resolv.conf' >> ~/.bashrc
echo "Listo! Variables agregadas al .bashrc"
else
echo "Las variables ya existen en .bashrc, no se duplicaron."
fi

source ~/.bashrc
echo "Todo listo! Ya puedes usar codex"

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Jose2021H I tried that excited that it might work, but I'm getting:

file:///data/data/com.termux/files/usr/lib/node_modules/@openai/codex/bin/codex.js:100      throw new Error(                                                                              ^
Error: Missing optional dependency @openai/codex-linux-arm64. Reinstall Codex: npm install -g @openai/codex@latest                                                                  at file:///data/data/com.termux/files/usr/lib/node_modules/@openai/codex/bin/codex.js:100:11                                                                                    at ModuleJob.run (node:internal/modules/esm/module_job:430:25)                          at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:639:26)
    at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:101:5)

Node.js v25.8.2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@licy183 someone tried to use codex from TUR, but because it doesn't work, they opened an issue, and because of that I sent them a link to this thread which they linked in their issue,

i assume that if wallentx is continuing with this, they will eventually be able to solve that issue

Copy link
Copy Markdown
Owner Author

@wallentx wallentx Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robertkirkman @tomiia @mevanlc
Things got pretty messy and broken for a bit, but I've done a lot of cleanup and have a fully working build here that is roughly equivalent to 0.122.0-alpha.5:
https://github.com/wallentx/codex/actions/runs/24577406145

I'm working on CI now that will mirror upstream pre-releases/releases as much as possible, then apply the Termux patch layer and produce an Android artifact from that result.

At this point the PR is less "one small Android target patch" and more a collection of compatibility fixes that will need to be applied to upstream code as it changes. My goal with the mirrored releases are to make this automated and maintainable, because I don't have high hopes that I'll be getting an invite to PR to OpenAI, and I don't suspect that any of this work is a high priority for them.

The current landscape of changes is roughly:

Android/Termux Runtime Fixes

  • Advisory file locks: Android/Bionic/Termux can return
    ErrorKind::Unsupported for Rust File::lock() / try_lock() style APIs.
    This was the cause of errors like:

    Error: thread/start failed during TUI bootstrap
    

    and:

    Failed to initialize session: lock() not supported
    

    I added a small shared helper crate for optional advisory file locking so call sites can distinguish "lock acquired", "would block", and "locking unsupported". There is also an audit script to help find future upstream lock usage that may need the same treatment.

  • File watcher behavior: The live filesystem watcher is disabled/nooped on Android. This avoids platform behavior that is not reliable in the Termux environment while still allowing the rest of the app to start normally.

  • Shell path resolution: Codex normally assumes standard Unix absolute paths like /bin/sh. On Termux those paths are not the real userland. I added Android-specific shell lookup that prefers $PREFIX/bin/..., falling back to Termux's usual /data/data/com.termux/files/usr/bin/... location when $PREFIX is unavailable.

  • Clipboard/image paste: Android builds exclude unsupported desktop clipboard/image-paste paths so the crate compiles cleanly and reports unsupported clipboard behavior instead of pulling in incompatible assumptions.

Login/Auth Fixes

  • Device-code auth: The branch includes the fixes needed for device-code auth to work on Termux. This currently does not work in upstream for this Android/Termux build target.

  • ChatGPT browser login duplicate callback: Device-code login worked first, but "Sign in with ChatGPT" failed on Android/Chrome after the browser hit the localhost callback more than once. The first callback successfully redeemed the OAuth code; the duplicate callback then tried to redeem the same code again and got a 400 from the token endpoint. The visible error was:

    Token exchange failed: token endpoint returned status 400 Bad Request:
    Invalid request. Please try again later.
    

    I added callback state tracking so duplicate callbacks for the same code either reuse the success redirect or wait briefly for the first callback to finish.

  • TUI originator compatibility: The app-server client name from the TUI is normalized back to the expected default originator for login/client behavior, while preserving the user-agent suffix.

Android Binary/Build Artifact Fixes

  • TLS alignment: The produced binary needed post-processing/alignment fixes for ARM64 Bionic. Before that, Termux reported:

    executable's TLS segment is underaligned: alignment is 64 (skew 16), needs to be at least 64 for ARM64 Bionic
    

    The workflow now runs the cleanup/alignment steps needed for the Android artifact.

  • Custom Android V8 artifact: For now I had to fork denoland/rusty_v8, make changes there to produce an Android artifact, and publish that artifact in a release so this Codex fork can fetch and use it:
    https://github.com/wallentx/rusty_v8/releases/tag/v146.9.0

    That is an external dependency I still need to chase upstream, because this should ideally come from the upstream rusty_v8 artifact pipeline rather than my fork.

Maintenance / Future-Proofing

  • Lock audit helper: Since upstream can add new lock() usage at any time, I added scripts/termux-lock-audit.sh / just termux-lock-audit to flag candidate file-lock call sites that may need Android/Termux handling.

  • Release automation: I'm setting up a release-train workflow so when upstream publishes a new rust-v* pre-release/release, my fork can create a release/<version-train> branch, apply the Termux patch layer, build the Android artifact in CI, let me manually test that exact artifact, and then promote that same artifact into a mirrored Termux release once the PR is merged.

Some of these feel like reasonable upstream candidates, especially the "unsupported file locks should be handled gracefully" pieces, device-code auth, and the duplicate OAuth callback handling. Others are probably downstream-only for now, especially Termux path assumptions, Android artifact post-processing, and the temporary dependency on my fork's V8 artifact.

This might seem like a lot of effort for a niche group of users, but it's something I want for myself, and I'm currently unemployed (holla if hiring for Staff/Principal DevOps), so this is also keeping me sane and busy.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wallentx and others added 20 commits April 24, 2026 22:52
…ckpoint/wallentx_termux-target_from_release_0.126.0_d763bfd051ab

# Conflicts:
#	codex-rs/Cargo.toml
…t_from_release_0.126.0_d763bfd051ab

checkpoint: into wallentx/termux-target from release/0.126.0 @ d763bfd
…ckpoint/wallentx_termux-target_from_release_0.126.0_c958229d879c

# Conflicts:
#	codex-rs/Cargo.toml
…t_from_release_0.126.0_c958229d879c

checkpoint: into wallentx/termux-target from release/0.126.0 @ c958229
….0-alpha.3

Release 0.126.0-alpha.3

# Conflicts:
#	.github/workflows/bazel.yml
#	.github/workflows/rust-release.yml
#	codex-rs/Cargo.toml
#	codex-rs/app-server/tests/suite/v2/thread_resume.rs
…nt/wallentx_termux-target_from_release_0.126.0_eb70bfad6fb4

# Conflicts:
#	.github/termux-release.json
#	.github/workflows/termux-release-checkpoint.yml
#	.github/workflows/termux-release-deploy.yml
…t_from_release_0.126.0_eb70bfad6fb4

checkpoint: into wallentx/termux-target from release/0.126.0 @ eb70bfa
wallentx and others added 30 commits May 5, 2026 20:32
…nt/wallentx_termux-target_from_release_0.129.0_1a78ed0ef81a

# Conflicts:
#	.github/workflows/rust-release.yml
#	.github/workflows/shell-tool-mcp.yml
#	codex-rs/Cargo.toml
#	scripts/termux-create-checkpoint-pr.sh
…t_from_release_0.129.0_1a78ed0ef81a

checkpoint: into wallentx/termux-target from release/0.129.0 @ 1a78ed0
## Why

The core protocol still exposed a `ListModels` submission op even though
no client sends it and the core submission loop treated it as an ignored
unknown op. Keeping the dead variant made the protocol surface look
supported while the active model listing API is the app-server
`model/list` JSON-RPC request.

## What Changed

- Removed the unused `Op::ListModels` variant from `codex-rs/protocol`.
- Removed its `Op::kind()` mapping.

The existing app-server `model/list` endpoint is unchanged.

## Verification

- `cargo test -p codex-protocol`
## Why

`skills/list` is already exposed through app-server v2 and covered by
the app-server test suite. Keeping the separate core `Op::ListSkills`
path leaves a duplicate legacy protocol surface that no longer needs to
be maintained.

## What Changed

- Removed `Op::ListSkills` and `EventMsg::ListSkillsResponse` from the
core protocol.
- Deleted the corresponding core session handler and stale core
integration tests.
- Removed rollout/MCP ignore branches and protocol v1 docs references
for the deleted event/op.
- Left app-server `skills/list` and its existing coverage intact.

## Validation

- `cargo test -p codex-protocol`
- `cargo test -p codex-core --test all suite::skills`
- `cargo check -p codex-mcp-server -p codex-rollout -p
codex-rollout-trace`
- `just fix -p codex-core`
## Summary
- Add plugin manifest keywords to core plugin marketplace/detail models
- Expose keywords on app-server v2 PluginSummary and generated
schema/types
- Populate keywords in plugin/list and plugin/read responses for local
plugins

Depends on openai/openai#891087

## Validation
- just fmt
- just write-app-server-schema
- cargo test -p codex-app-server-protocol
- cargo test -p codex-core-plugins
- cargo test -p codex-app-server
plugin_list_keeps_valid_marketplaces_when_another_marketplace_fails_to_load
- cargo test -p codex-app-server
plugin_read_returns_plugin_details_with_bundle_contents
…0949)

## Summary
- make `thread_source` an explicit optional thread-level field on
`thread/start`, `thread/fork`, and returned thread payloads
- persist `thread_source` in rollout/session metadata so resumed live
threads retain the original value
- replace the old best-effort `session_source` -> `thread_source`
mapping with an explicit caller-supplied analytics classification

## Why
Before this change, analytics `thread_source` was populated by a
best-effort mapping from `session_source`. `session_source` describes
the runtime/client surface, not the actual thread-level origin, so that
projection was not accurate enough to distinguish cases such as `user`,
`subagent`, `memory_consolidation`, and future thread origins reliably.

Making `thread_source` explicit keeps one thread-level analytics field
while letting callers provide the real classification directly instead
of recovering it indirectly from `session_source`.

## Impact
For new analytics events, `thread_source` now reflects the explicit
thread-level classification supplied by the caller rather than an
inferred value derived from `session_source`. Existing protocol fields
remain optional; callers that omit `threadSource` now produce `null`
instead of a best-effort inferred value.

## Validation
- `just write-app-server-schema`
- `cargo test -p codex-analytics -p codex-core -p
codex-app-server-protocol --no-run`
- `cargo test -p codex-app-server-protocol
generated_ts_optional_nullable_fields_only_in_params`
- `cargo test -p codex-analytics
thread_initialized_event_serializes_expected_shape`
- `cargo test -p codex-core
resume_stopped_thread_from_rollout_preserves_thread_source`
Extends `plugin/share/save` to accept optional discoverability and
shareTargets while uploading plugin contents, and adds
`plugin/share/updateTargets` for share-only target updates without
re-uploading.
…nt/wallentx_termux-target_from_release_0.129.0_bfb0621cfd50

# Conflicts:
#	.github/workflows/rust-release.yml
#	.github/workflows/shell-tool-mcp.yml
#	codex-rs/Cargo.toml
#	scripts/termux-create-checkpoint-pr.sh
…#20724)

## Why

Codex currently accepts dynamic tool names and namespaces that the
upstream Responses function-tool path does not actually support. In
practice, that means app-server can register a dynamic tool successfully
and only discover later that the LLM-facing tool contract will reject or
mishandle it.

This PR tightens the app-server-side dynamic tool contract to match the
Responses API before we stack dynamic tool hook support on top of it.

## What changed

- validate dynamic tool `name` against the Responses function-tool
identifier contract: `^[a-zA-Z0-9_-]+$`, length `1..128`
- validate dynamic tool `namespace` the same way, with the Responses
namespace length limit `1..64`
- reject namespaces that collide with the always-reserved Responses
runtime namespaces such as `functions`, `multi_tool_use`, `file_search`,
`web`, `browser`, `image_gen`, `computer`, `container`, `terminal`,
`python`, `python_user_visible`, `api_tool`, `tool_search`, and
`submodel_delegator`
- escape invalid identifiers in error messages so control characters do
not spill raw into logs or client-visible error text
- document the tightened dynamic tool identifier contract in
`codex-rs/app-server/README.md`
- add both unit coverage for the validator and an app-server integration
test that rejects a `thread/start` request with Responses-incompatible
dynamic tool identifiers

## Verification

- `cargo test -p codex-app-server validate_dynamic_tools_`
- `cargo test -p codex-app-server --test all
thread_start_rejects_dynamic_tools_not_supported_by_responses`
# Overview
MCP refreshes were rebuilding active threads from fresh disk-backed
config only, which dropped thread-start session overlays such as
app-injected MCP servers. This keeps refreshes current with disk config
while preserving the thread-local config that only the active thread
knows about.

# Changes
- Rebuild refreshed config per active thread using that thread's current
`cwd`, rather than fanning out one app-server config to every thread.
- Preserve each thread's `SessionFlags` layer while replacing reloadable
config layers with freshly loaded config, then derive the MCP refresh
payload from the rebuilt result.
- Move MCP refresh orchestration into app-server so manual refreshes
fail loudly while background refreshes remain best-effort, and route
plugin-triggered refreshes through the same per-thread reload path.
- Add regression coverage for session overlays, fresh project config,
plugin-derived MCP config, current requirements, and strict vs
best-effort refresh behavior.

# Verification
- Passed focused Rust coverage for the thread-config rebuild behavior
and deferred MCP refresh flow, plus `cargo test -p codex-app-server
--lib`.
- Verified end to end in the Codex dev app against the locally built
CLI: registered an MCP via thread config, verified that it could be used
successfully before refresh, manually triggered MCP refresh, and
verified that it continued to be available afterward.
- [x] Return Accept early when auto_deny is enabled per feedback.
## Why

openai#21255 added the standalone `codex-bwrap` binary. In the Cargo build,
[`pkg_config::probe("libcap")`](https://github.com/openai/codex/blob/a736cb55a2bce57b4c8e5a4fe56f70c2b2ad892b/codex-rs/bwrap/build.rs#L37-L39)
emits `-lcap` before
[`cc::Build::compile("standalone_bwrap")`](https://github.com/openai/codex/blob/a736cb55a2bce57b4c8e5a4fe56f70c2b2ad892b/codex-rs/bwrap/build.rs#L50-L67)
adds the static bwrap archive. The Linux musl link then sees `-lcap
-lstandalone_bwrap`; because static archives are resolved left-to-right,
`cap_from_name` is still undefined once `standalone_bwrap` introduces
that reference.

The musl setup already builds `libcap.a` and exposes it through
[`libcap.pc`](https://github.com/openai/codex/blob/a736cb55a2bce57b4c8e5a4fe56f70c2b2ad892b/.github/scripts/install-musl-build-tools.sh#L78-L88),
so the failure is link ordering rather than a missing dependency.

## What changed

- probe `libcap` with `cargo_metadata(false)` so `pkg-config` does not
emit its link flags early
- emit the discovered `libcap` search paths and libraries after
`standalone_bwrap` is compiled, preserving the needed static-link order

## Verification

- `cargo test -p codex-bwrap`
- `cargo clippy -p codex-bwrap --all-targets`

The affected Linux musl release link is exercised by CI, which is the
path this fix targets.
…t_from_release_0.129.0_bfb0621cfd50

checkpoint: into wallentx/termux-target from release/0.129.0 @ bfb0621
## Why

openai#21255 changed the Linux sandbox fallback so Codex can use a bundled
`codex-resources/bwrap` executable when no suitable system `bwrap` is
available. That lookup is relative to the native Codex executable
returned by
`std::env::current_exe()`, as implemented in
[`bundled_bwrap.rs`](https://github.com/openai/codex/blob/9766d3d51cec885114b6d6c53a02e9efbaf87171/codex-rs/linux-sandbox/src/bundled_bwrap.rs#L83-L93).

The release already publishes a separate `bwrap` DotSlash output, but
the Linux `codex` DotSlash output still pointed at a single-binary
`.zst` payload. Running the `codex` DotSlash manifest only materializes
the native `codex` executable; it does not also create sibling files
from the separate `bwrap` manifest. The fallback path therefore needs
the Linux `codex` DotSlash artifact itself to include the real `bwrap`
executable at `codex-resources/bwrap`.

## What changed

- stage a Linux primary `codex-<target>-bundle.tar.zst` release artifact
containing `codex` and `codex-resources/bwrap`
- point the Linux `codex` DotSlash outputs at that bundle tarball
- leave the standalone `bwrap` DotSlash output in place for consumers
that want to fetch `bwrap` directly

## Verification

- `jq . .github/dotslash-config.json`
- Ruby YAML parse of `.github/workflows/rust-release.yml`
…nt/wallentx_termux-target_from_release_0.129.0_b187e52ce92d

# Conflicts:
#	.github/workflows/rust-release.yml
#	.github/workflows/shell-tool-mcp.yml
#	codex-rs/Cargo.toml
#	scripts/termux-create-checkpoint-pr.sh
…t_from_release_0.129.0_b187e52ce92d

checkpoint: into wallentx/termux-target from release/0.129.0 @ b187e52
…nt/wallentx_termux-target_from_release_0.129.0_685f3524f4fe

# Conflicts:
#	.github/workflows/rust-release.yml
#	.github/workflows/shell-tool-mcp.yml
#	codex-rs/Cargo.toml
#	scripts/termux-create-checkpoint-pr.sh
…t_from_release_0.129.0_685f3524f4fe

checkpoint: into wallentx/termux-target from release/0.129.0 @ 685f352
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.