Install this version:
emerge -a =dev-util/codex-0.166.0
If this version is masked, you can unmask it using the autounmask tool or standard emerge options:
autounmask =dev-util/codex-0.166.0
Or alternatively:
emerge --autounmask-write -a =dev-util/codex-0.166.0
| Version | EAPI | Keywords | Slot |
|---|---|---|---|
| 0.166.0 | 8 | -* ~amd64 | 0 |
# Copyright 1999-2026 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=8
# NOTE: This package uses a pre-built crate tarball instead of listing individual
# crates in CRATES="". This approach is required because:
# 1. Codex has 800+ crate dependencies, which triggers Portage QA warnings:
# "QA Notice: This package uses a very large number of CRATES. Please provide
# a crate tarball instead and fetch it via SRC_URI."
# 2. Stricter ebuild QA checks (e.g., in CI pipelines) fail with too many crates.
#
# The crate tarball is auto-generated by GitHub Actions at:
# https://github.com/gentoo-zh-drafts/codex/
# Workflow source code for auditing:
# https://github.com/gentoo-zh-drafts/codex/blob/crate-dist/.github/workflows/crates.yml
# This allows anyone to review and verify the crate packaging process.
CRATES="
"
# Mirrors every "source = git+..." entry in codex-rs/Cargo.lock. Diff this block
# against that file on every bump; an entry the lock no longer references only
# costs a pointless fetch, but a stale rev is silent here. src_prepare rewrites
# [patch.crates-io] as "path = <unpacked dir>", and a path carries no revision,
# so cargo never reports "can't checkout <repo>#<rev>" -- it just compiles the
# previous release's source. That surfaces much later as unrelated-looking
# errors in a consumer crate: 0.148.0 with the 0.147.0 crossterm failed with
# E0425/E0433 in codex-tui for discard_buffered_input, buffer_input and
# InputDiscardStatus, all added by the fork after f69a4a04.
# Upstream moved crossterm from nornagon to openai-oss-forks in 0.147.0 and
# dropped its ratatui fork back to crates.io.
#
# A git repository holding several workspace members gets one entry per member
# the lock references, all pointing at the same commit. That is not redundancy:
# the eclass emits one "<crate> = { path = ... }" line per key under a single
# [patch.'<uri>'] block, and a member with no key is left resolving to the git
# source, which dies under --offline with "can't checkout <repo>". SRC_URI and
# DISTDIR see the same tarball several times and deduplicate it. That covers
# nucleo/nucleo-matcher, hyperium/h3 (h3 + h3-quinn, since 0.156.0) and
# modelcontextprotocol/rust-sdk (rmcp + rmcp-macros, since 0.161.0).
#
# 0.166.0 moved v8 under [patch.crates-io] to a fork (seanh-oai/rusty_v8)
# whose only change is src/cppgc.rs, so the prebuilt RUSTY_V8_TAG archive and
# its binding still match. The GitHub tarball lacks the V8 submodules; that is
# fine because build.rs never reads them when RUSTY_V8_ARCHIVE is set. Without
# this entry cargo looks for v8 in the crates tarball and dies with "no
# matching package named `v8` found".
#
# microsoft/mxc held eight such members up to 0.163; 0.164.0 replaced all of
# them with a single mxc-sdk crate (src/mxc-sdk), reached by the new
# codex-rs/mxc-sandbox workspace member, and moved the commit with it. Keeping
# the eight old keys failed exactly as above, because mxc-sdk had none.
#
# Windows-only git dependencies are vendored anyway, because cargo resolves the
# whole dependency graph before it ever looks at the target, so a
# Windows-gated git dependency still has to be fetchable. Deleting them from
# Cargo.toml instead would work and would be a divergence from upstream's lock
# to re-apply, and re-verify, on every bump.
declare -A GIT_CRATES=(
[mxc-sdk]='https://github.com/microsoft/mxc;b21120168d70befe12356411423266bfef168446;mxc-%commit%/src/mxc-sdk'
[crossterm]='https://github.com/openai-oss-forks/crossterm;ed1cdab335221515706178d68495bba2aed1924f;crossterm-%commit%'
[h3-quinn]='https://github.com/hyperium/h3;e07e69412876f7e26f026bd75a48b2704d8c8283;h3-%commit%/h3-quinn'
[h3]='https://github.com/hyperium/h3;e07e69412876f7e26f026bd75a48b2704d8c8283;h3-%commit%/h3'
[nucleo-matcher]='https://github.com/helix-editor/nucleo;4253de9faabb4e5c6d81d946a5e35a90f87347ee;nucleo-%commit%/matcher'
[nucleo]='https://github.com/helix-editor/nucleo;4253de9faabb4e5c6d81d946a5e35a90f87347ee;nucleo-%commit%'
[rmcp-macros]='https://github.com/modelcontextprotocol/rust-sdk;98a54789b80110ad210495c4ad845c89e1980471;rust-sdk-%commit%/crates/rmcp-macros'
[rmcp]='https://github.com/modelcontextprotocol/rust-sdk;98a54789b80110ad210495c4ad845c89e1980471;rust-sdk-%commit%/crates/rmcp'
[runfiles]='https://github.com/dzbarsky/rules_rust;b56cbaa8465e74127f1ea216f813cd377295ad81;rules_rust-%commit%/rust/runfiles'
[tokio-tungstenite]='https://github.com/openai-oss-forks/tokio-tungstenite;0e5b2d73aa18dd9f0a50ee9ff199d5aef7594186;tokio-tungstenite-%commit%'
[tungstenite]='https://github.com/openai-oss-forks/tungstenite-rs;4fffad30fe373adbdcffab9545e9e9bf4f2fc19f;tungstenite-rs-%commit%'
[v8]='https://github.com/seanh-oai/rusty_v8;350c5a859a9b3c84ab8701b3ad51e3b7699b30c0;rusty_v8-%commit%'
)
RUST_MIN_VER="1.95.0"
# Tag of the crate tarball published by the crate-dist fork
# (gentoo-zh-drafts/codex). It is derived from PV rather than written out,
# because the failure mode of the two choices is not symmetric. Deriving it and
# guessing wrong means the fetch 404s -- loud, before a single crate compiles.
# Writing it out and forgetting to raise it vendors the PREVIOUS release's
# crates, and cargo then dies deep in the build on whichever dependency moved
# ("failed to select a version for the requirement"), reading like an upstream
# bug rather than a stale pin.
#
# That is not hypothetical: it stayed at a literal rust-v0.150.0 across the
# 0.151, 0.152 and 0.153 bumps, and that vendor directory is missing six crates
# the 0.153.0 lock needs -- cidr, flatbuffers, tracelogging, tracelogging_macros,
# unicode-general-category, winreg.
#
# Replace it with a literal ONLY when the fork published no tarball for this
# release AND the two codex-rs/Cargo.lock files are byte-identical; say which
# tag and why, as the 0.150.1 case did (both locks hashed
# beb9a924bf01f03ecfa9fedbf50a602cbaa5399df5cbe57e2d6bd40529e055a6).
MY_CRATES_TAG="rust-v${PV}"
# Version of the prebuilt V8 static library, which MUST equal the version of
# the "v8" crate the lock resolves -- the archive ships its own FFI bindings
# (RUSTY_V8_SRC_BINDING_PATH), so a mismatched pair compiles against one ABI
# and links against another. Upstream documents this as
# ".github/scripts/rusty_v8_bazel.py resolved-v8-crate-version", but that
# script is not runnable outside their Bazel checkout (it imports
# run_bazel_with_buildbuddy). Read it off the lock instead:
#
# awk '/^name = "v8"$/{f=1} f&&/^version = /{print $3; exit}' codex-rs/Cargo.lock
#
# It was stale at 147.4.0 while the lock had already moved to 150.4.0.
RUSTY_V8_TAG="152.2.0"
inherit cargo
DESCRIPTION="Codex CLI - OpenAI's AI-powered coding agent"
HOMEPAGE="https://github.com/openai/codex"
# The crate tarball URL uses ${PV} so it auto-updates when bumping versions.
# This tarball is generated by: https://github.com/gentoo-zh-drafts/codex/
# See .github/workflows/crates.yml for the generation process.
SRC_URI="
https://github.com/openai/${PN}/archive/rust-v${PV}.tar.gz -> ${P}.tar.gz
https://github.com/gentoo-zh-drafts/codex/releases/download/${MY_CRATES_TAG}/codex-${MY_CRATES_TAG}-crates.tar.xz
amd64? (
https://github.com/openai/codex/releases/download/rusty-v8-v${RUSTY_V8_TAG}/librusty_v8_release_x86_64-unknown-linux-musl.a.gz
-> rusty_v8_${RUSTY_V8_TAG}_librusty_v8_release_x86_64-unknown-linux-musl.a.gz
https://github.com/openai/codex/releases/download/rusty-v8-v${RUSTY_V8_TAG}/src_binding_release_x86_64-unknown-linux-musl.rs
-> rusty_v8_${RUSTY_V8_TAG}_src_binding_release_x86_64-unknown-linux-musl.rs
)
${CARGO_CRATE_URIS}
"
S="${WORKDIR}/${PN}-rust-v${PV}/codex-rs"
LICENSE="Apache-2.0"
# Dependent crate licenses
LICENSE+="
Apache-2.0 Apache-2.0-with-LLVM-exceptions BSD-2 BSD Boost-1.0
CC0-1.0 CDLA-Permissive-2.0 ISC MIT MPL-2.0 Unicode-3.0 ZLIB
"
SLOT="0"
KEYWORDS="-* ~amd64"
# Tests fail due to ring crate conflicts with system OpenSSL
RESTRICT="test"
DEPEND="
dev-libs/openssl:=
sys-apps/dbus
"
RDEPEND="${DEPEND}"
BDEPEND="virtual/pkgconfig"
# rust does not use *FLAGS from make.conf, silence portage warning
QA_FLAGS_IGNORED="usr/bin/${PN}"
gen_git_crate_dir() {
# https://github.com/gentoo/gentoo/blob/b09dd88412fe2d5eee5a8891e08bfa2d67848da3/eclass/cargo.eclass#L442
IFS=';' read -r crate_uri commit crate_dir <<<"${GIT_CRATES[$1]}"
echo "${WORKDIR}/${crate_dir//%commit%/${commit}}"
}
src_prepare() {
default
# Fix tokio-tungstenite's git dependency on tungstenite
sed -i '/^\[dependencies\.tungstenite\]/,/^$/{
s|git = "https://github.com/openai-oss-forks/tungstenite-rs"|path = "'"$(gen_git_crate_dir tungstenite)"'"|
/^rev = /d
}' "$(gen_git_crate_dir tokio-tungstenite)/Cargo.toml" || die
# rustc 1.98 counts the layout query of an async fn body against
# recursion_limit, and codex-chatgpt's connectors::list_connectors() adds
# 130 to the depth on its own -- past the default of 128, which aborts the
# crate with "queries overflow the depth limit!". Upstream never sees it
# (their toolchain accounts the query differently), so the crate root
# carried no attribute of its own; the guard exists because inserting a
# second #![recursion_limit] once upstream adds one is a hard error.
# By 0.161.0 the crate mentions recursion_limit itself, so only insert ours
# when no crate-level attribute is present.
if ! grep -q '^[[:space:]]*#!\[recursion_limit' chatgpt/src/lib.rs; then
sed -i '1i #![recursion_limit = "512"]' chatgpt/src/lib.rs || die
fi
# Remove the [patch.crates-io] section and add path-based patches
sed -i '/^\[patch\.crates-io\]/,/^$/d' "${S}/Cargo.toml" || die
sed -i '/^\[patch\."ssh:\/\/git@github\.com/,/^$/d' "${S}/Cargo.toml" || die
# Add new patch section with local paths
cat >> "${S}/Cargo.toml" <<-EOF || die
[patch.crates-io]
crossterm = { path = "$(gen_git_crate_dir crossterm)" }
tokio-tungstenite = { path = "$(gen_git_crate_dir tokio-tungstenite)" }
tungstenite = { path = "$(gen_git_crate_dir tungstenite)" }
v8 = { path = "$(gen_git_crate_dir v8)" }
EOF
}
src_compile() {
local rusty_v8_triple
use amd64 && rusty_v8_triple=x86_64-unknown-linux-musl
RUSTY_V8_ARCHIVE="${DISTDIR}/rusty_v8_${RUSTY_V8_TAG}_librusty_v8_release_${rusty_v8_triple}.a.gz" \
RUSTY_V8_SRC_BINDING_PATH="${DISTDIR}/rusty_v8_${RUSTY_V8_TAG}_src_binding_release_${rusty_v8_triple}.rs" \
cargo_src_compile --package codex-cli
}
src_install() {
dobin "$(cargo_target_dir)/codex"
einstalldocs
}
dev-libs/openssl:= sys-apps/dbus
dev-libs/openssl:= sys-apps/dbus
virtual/pkgconfig