Codex App enables worktreeConfig in a bare common-dir and breaks every linked worktree

Open 💬 0 comments Opened Jul 22, 2026 by jomoskus

What version of the Codex App are you using?

Codex Desktop 26.715.52143, build 5591

Bundled CLI: codex-cli 0.145.0-alpha.18

What platform is your computer?

macOS 26.5.2 build 25F84, arm64

What issue are you seeing?

Creating a Codex-managed worktree from a valid linked checkout whose common directory is a bare repository mutates the shared Git config in a way that makes every linked worktree appear bare.

The repository layout was:

workspace/
  repo/                    # bare repository/common-dir
  linked-worktree-a/
  linked-worktree-b/
  ...                      # 115 linked worktrees
  codex-source/            # valid linked checkout selected as the Codex project

Before the Codex operation:

  • extensions.worktreeConfig was unset in the shared config.
  • core.bare=true was present in the bare common config.
  • git status and git rev-parse --is-inside-work-tree worked in all linked worktrees.
  • The selected project passed --show-toplevel, --is-inside-work-tree=true, and --is-bare-repository=false.

Starting one worktree-backed Codex thread then:

  1. Created the managed detached worktree.
  2. Added this to the shared bare common config:

``ini
[extensions]
worktreeConfig = true
``

  1. Created only this per-worktree file for the managed worktree:

``ini
[codex]
localEnvironmentConfigPath = __none__
``

  1. Left core.bare=true in the shared config.

Immediately afterward, the managed worktree and every existing linked worktree returned:

git rev-parse --is-inside-work-tree
false

git rev-parse --is-bare-repository
true

git status
fatal: this operation must be run in a work tree

The shared config's modification time matched the Codex provisioning attempt. Only two config.worktree files existed across the 115 linked worktrees, so there was no per-worktree core.bare=false override for the others.

This behavior matches Git's documented warning: once extensions.worktreeConfig is enabled, the special main-worktree-only treatment of core.bare is gone, and a shared core.bare=true must be moved out of the common config. See git-worktree: Configuration File.

Recovery and controlled validation

Removing only the extension that Codex had just added restored all linked worktrees immediately:

git --git-dir=<common-dir> config --unset extensions.worktreeConfig

No source changes were lost.

I then replaced the Codex source project with a fully independent ordinary clone whose own common config has core.bare=false. A second Codex-managed worktree spawn succeeded:

  • a pending client ID became a regular thread ID;
  • the managed cwd was under $CODEX_HOME/worktrees;
  • --is-inside-work-tree=true;
  • --is-bare-repository=false;
  • detached HEAD at the expected commit;
  • clean status;
  • archive cleanup removed the managed worktree.

The original bare common-dir remained untouched during this successful run.

Expected behavior

Codex should not leave a bare common-dir in this invalid mixed configuration.

Before enabling extensions.worktreeConfig, provisioning should either:

  1. detect core.bare=true in the common config and avoid enabling the extension;
  2. perform the complete Git-prescribed migration safely for the bare main repository and every existing linked worktree; or
  3. reject this topology with an actionable error and recommend an independent non-bare clone.

A failed or partial migration must be rolled back before returning control. This write occurs outside the model sandbox and can disrupt every checkout sharing the repository.

Related issues

  • #28204 tracks worktree-init failures that expose no recoverable error to a parent create_thread caller.
  • #26338 tracks parent workspaces containing child repositories.

This report is separate because the selected source root was a valid Git working tree; the failure is a shared Git-config mutation during managed-worktree provisioning.

View original on GitHub ↗