Memory consolidation hard-requires the `git` binary (`git read-tree`) — silent failure, and macOS CLT install prompt, on machines without git
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.5k
- PR merge metrics
- PR metrics pending
Description
What issue are you seeing?
Memory consolidation's git baseline (codex-rs/memories/write) hard-requires
the external git binary for one specific step, even though every other
part of the baseline is already implemented on top of gitoxide (gix).
On a machine where git is not installed, or not resolvable on PATH
without a side effect, this step silently fails every time a memory
consolidation workspace is (re)initialized.
Concretely:
prepare_memory_workspace(codex-rs/memories/write/src/workspace.rs)
callscodex_git_utils::ensure_git_baseline_repository, and
reset_memory_workspace_baselinecallscodex_git_utils::reset_git_repository.- Both funnel into
reset_git_repository_syncin
codex-rs/git-utils/src/baseline.rs, which:gix::init(root)— in-process, gitoxide.commit_current_tree(&repo, ...)— in-process, gitoxide (writes blobs/
tree/commit viagix::Repository::write_object/commit_as).write_index_from_head(root)— shells out:fn write_index_from_head(root: &Path) -> anyhow::Result<()> { run_git_for_status(root, ["read-tree", "--reset", "HEAD"], /*env*/ None) .context("write git baseline index from HEAD") }run_git_for_status(codex-rs/git-utils/src/operations.rs) calls
run_git, which doesCommand::new("git").
That one shell-out is the only reason this baseline needs a system git
binary at all.
Impact:
- Silent failure everywhere
gitis missing/unresolvable. Phase 2
logs this asfailed_prepare_workspace(on first init,
codex-rs/memories/write/src/phase2.rsaround line 73-83) and
failed_workspace_commit(after every successful consolidation, around
line 462) — there is no user-facing surfacing of this, memory
consolidation just stops updating. - A GUI popup on macOS specifically, for any host embedding the Codex
engine (app-server, Electron/Tauri wrappers, etc.) on a machine without
the Xcode Command Line Tools installed./usr/bin/giton stock macOS is
Apple'sxcode-selectshim (linkslibxcselect.dylib); when a GUI
process spawns it as a child, macOS raises a blocking "The 'git' command
requires the command line developer tools. Would you like to install the
tools now?" dialog instead of just failing fast. This exact behavior for
GUI-spawnedgitchild processes is documented for other Electron/GUI
apps that shell out togit, e.g. Zettlr
(https://github.com/Zettlr/Zettlr/issues/4709), CodeEdit
(https://github.com/CodeEditApp/CodeEdit/issues/2138), and was reported
for Claude Desktop (https://www.eclecticlight.co, 2026-03-17). So on a
fresh macOS machine with no dev tools installed, simply having memories
enabled in a GUI Codex host can pop an OS dialog on first consolidation.
Also worth flagging while reading this code (not the primary bug, but
adjacent, please correct me if I'm misreading it): ensure_git_baseline_repository
treats an existing .git/ as "usable" if gix::open succeeds and HEAD
has a tree — it does not check that the index exists/matches. So if
write_index_from_head fails (as it does whenever git is missing), the
commit from step 2 above is still written, and a subsequent call sees a
.git with a valid HEAD tree and treats it as already-initialized,
without ever retrying the index write. I haven't fully traced every caller
to confirm user-visible consequences, but it looks like a half-initialized
baseline (commit present, index absent/stale) can be silently treated as
valid on retry.
What steps can reproduce the bug?
- On a machine with no
gitbinary anywhere onPATH(or, to reproduce
without uninstalling anything: temporarily run the process with
PATHpointed at a directory that has nogitin it), enable memories
and run any session that triggers phase-2 consolidation. - Observe that
reset_git_repository/ensure_git_baseline_repository
fail — surfaced only asfailed_prepare_workspace/
failed_workspace_commitlog entries in
codex-rs/memories/write/src/phase2.rs, no user-facing error. - On macOS without the Command Line Tools, instead of a hard failure you
get the "install developer tools?" dialog described above, because
/usr/bin/gitis thexcode-selectshim rather than a realgit.
Root cause, with exact file paths and the call chain:
codex-rs/memories/write/src/workspace.rs:prepare_memory_workspace->
codex_git_utils::ensure_git_baseline_repository;
reset_memory_workspace_baseline->codex_git_utils::reset_git_repository.codex-rs/git-utils/src/baseline.rs:reset_git_repository_synccalls
gix::init+commit_current_tree(both gitoxide, in-process), then
write_index_from_head(root), which is
run_git_for_status(root, ["read-tree", "--reset", "HEAD"], None)—
the one line in this whole module that isn't gitoxide.codex-rs/git-utils/src/operations.rs:run_git_for_status->run_git
->Command::new("git").
Verified against the vendored rust-v0.147.0 copy of codex-rs and
re-confirmed against openai/codex@main (commit 9ded177 as of this
writing) — the code is identical on main.
What is the expected behavior?
Memory baseline init/reset should not require an external git binary at
all, matching the rest of codex-rs/git-utils/src/baseline.rs, which is
already fully gitoxide-based. write_index_from_head should build the
index in-process from the HEAD tree instead of shelling out.
Additional information
I have a small, tested fix ready on a branch on my fork, and would like an
invitation to open a PR per docs/contributing.md
("External contributions are by invitation only ... open an issue with your
analysis and a proposed fix; the maintainers will invite a PR if it's a
good fit").
Branch (compare against main):
https://github.com/openai/codex/compare/main...hesong12:codex:fix/memories-baseline-without-git-binary
Summary of the fix:
codex-rs/Cargo.toml: add the"index"feature to thegixdependency
(gix-indexwas already present inCargo.lockvia other transitive
features, so this is a zero-churnCargo.lockchange —gix-indexand
gix-lockversions are unchanged).codex-rs/git-utils/src/baseline.rs:write_index_from_headnow opens
the repo, resolvesHEAD's tree viaRepository::head_tree_id, builds
the index from it viaRepository::index_from_tree(which already
targets<git_dir>/indexas its path), and writes it with
gix_index::File::write. Behavior is unchanged: the index ends up
identical to theHEADtree, sogit statusin that directory is clean
anddiff_since_latest_initreports no changes, same as before.codex-rs/git-utils/src/operations.rs: removedrun_git_for_status,
which had no other callers left after this change (would otherwise be
dead code under-D warnings, per yourcargo clippy --tests -- -D warningsCI step).- Added a regression test in
codex-rs/git-utils/src/baseline.rsthat runs
reset_git_repository/diff_since_latest_initin a child process
withPATHpointed at an empty directory (nogitbinary resolvable at
all), and asserts the resulting.git/indexexactly matches theHEAD
tree. The child-process isolation is deliberate: this crate's other
tests legitimately shell out togitfor their own assertions (e.g.
git status --porcelain), and those would spuriously fail if the "no
git on PATH" condition were applied to the whole test process instead of
a dedicated child.
Locally verified on this branch, from codex-rs/:
cargo test -p codex-git-utils— 39 passed, 0 failed (stable across
repeated runs).cargo test -p codex-memories-write— 40 passed, 0 failed (including
workspace::tests::prepare_memory_workspace_recovers_unusable_git_dir
andworkspace::tests::reset_memory_workspace_baseline_removes_generated_diff,
which exercise the changed code path directly).cargo fmt -p codex-git-utils -p codex-memories-write -- --check— clean.cargo clippy -p codex-git-utils -p codex-memories-write --all-targets -- -D warnings— clean, matching.github/workflows/rust-ci-full.yml's
clippy invocation.
Happy to submit this as a PR if the team wants to invite it, per
docs/contributing.md.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with codex-rs/git-utils/src/baseline.rs, especially reset_git_repository_sync and write_index_from_head, then trace the callers in memories/write/src/workspace.rs. Run cargo test -p codex-git-utils and cargo test -p codex-memories-write. Done means baseline initialization and reset work with no git binary on PATH, the index matches HEAD, and the existing checks pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- git, rust
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 42/100