Codex App Remote SSH handoff fails at "Applying uncommitted changes to worktree" even when local and remote checkouts are clean, matching, and git worktree works manually

Open 💬 3 comments Opened Jul 9, 2026 by itsklimov

Body

What version of the Codex App are you using?

  • Codex App: 26.623.141536 (CFBundleVersion=4753, com.openai.codex)
  • Bundled Codex inside the macOS app: codex-cli 0.142.5
  • codex doctor from the bundled app reports: 0.143.0 available (current 0.142.5)
  • Separately installed local CLI: codex-cli 0.143.0
  • Remote SSH host Codex: codex-cli 0.143.0

Note: the macOS app was reinstalled from the official download, but its bundled
Codex binary still reports 0.142.5 while the separately installed CLI and the
remote standalone install report 0.143.0. This may or may not be relevant to
the handoff path.

Platform

Local Codex App host:

  • macOS 26.5.1, build 25F80
  • Darwin 25.5.0, arm64
  • Git 2.55.0
  • uv 0.9.10
  • Bun 1.3.14
  • Node v26.5.0
  • npm 11.17.0
  • pnpm 10.31.0

Remote SSH host:

  • Linux Mint 22.3
  • Kernel 6.17.0-23-generic, x86_64
  • Git 2.43.0
  • uv 0.11.28
  • Bun 1.3.14
  • Node v24.18.0
  • npm 11.16.0
  • pnpm 11.10.0
  • Codex installed as standalone package under ~/.codex/packages/standalone/releases/0.143.0-x86_64-unknown-linux-musl

Issue summary

Remote SSH projects are configured and normal remote threads can run. However, handing off a thread between the local Mac checkout and the SSH-host checkout consistently fails after Codex reports that it has copied files and created a new worktree.

The modal reaches:

Preparing files for transfer
Copying files to the destination host
Creating a new worktree
Applying uncommitted changes to worktree

Then the handoff fails with:

Hand-off to <ssh-host> failed
Failed to continue on another host: Destination checkout is already using the handoff branch, and Codex could not switch it to a default branch

This reproduces even after verifying that the local and remote checkouts are clean, on the same branch, at the same commit, have the same remote URL, and can create/remove git worktrees manually on both machines.

Names, repository URLs, usernames, host aliases, commit hashes, thread IDs, and
private file names are intentionally redacted below. The placeholders preserve
the relevant relationships, such as "local and remote are the same commit"
without publishing private identifiers.

Expected behavior

Handoff should succeed when:

  • the local and remote projects represent the same repository,
  • both checkouts are on main,
  • both checkouts are clean,
  • both checkouts have the same HEAD,
  • git worktree add/remove works manually on both machines,
  • Codex remote SSH app-server is healthy.

If handoff cannot proceed, the error should identify the actual branch/worktree/ref/path that blocks it.

Actual behavior

Handoff consistently fails at "Applying uncommitted changes to worktree" with the generic "Destination checkout is already using the handoff branch" error.

From the user's point of view, this happens both with no meaningful code changes and with a tiny tracked test change.

The same error was observed while trying to hand off between the SSH host and
"this computer" in both directions. The concrete reproduction steps below focus
on the local Mac checkout -> SSH host case because that is the path with the
most complete validation data.

Project layout used for reproduction

Example project: private Git repository, sanitized here as repo-a.

Local checkout:

/Users/<local-user>/Documents/Dev/code/repo-a

Remote SSH checkout:

/home/<remote-user>/Documents/code/repo-a

Both are normal primary checkouts, not linked worktrees.

Sanitized verification:

LOCAL repo-a ## main...origin/main HEAD=<same-commit-repo-a>
REMOTE repo-a ## main...origin/main HEAD=<same-commit-repo-a>

LOCAL worktree:
worktree /Users/<local-user>/Documents/Dev/code/repo-a
HEAD <same-commit-repo-a>
branch refs/heads/main

REMOTE worktree:
worktree /home/<remote-user>/Documents/code/repo-a
HEAD <same-commit-repo-a>
branch refs/heads/main

The same handoff failure was also observed on another private repository sanitized here as repo-b:

LOCAL repo-b ## main...origin/main HEAD=<same-commit-repo-b>
REMOTE repo-b ## main...origin/main HEAD=<same-commit-repo-b>

Additional mirrors were checked and aligned:

LOCAL repo-c ## main...origin/main HEAD=<same-commit-repo-c>
REMOTE repo-c ## main...origin/main HEAD=<same-commit-repo-c>

LOCAL repo-d ## main...origin/main HEAD=<same-commit-repo-d>
REMOTE repo-d ## main...origin/main HEAD=<same-commit-repo-d>

LOCAL repo-e ## main...origin/main HEAD=<same-commit-repo-e>
REMOTE repo-e ## main...origin/main HEAD=<same-commit-repo-e>

Remote SSH / Codex setup

The SSH host is configured through Codex App Settings -> Connections and discovered from ~/.ssh/config.

Remote codex doctor --summary:

Codex Doctor v0.143.0 · linux-x86_64

Environment
  ✓ system       en-US
  ✓ runtime      standalone
  ✓ install      consistent
  ✓ search       file exists (bundled rg)
  ✓ git          git version 2.43.0
  ✓ terminal     unknown
  ✓ title        default · project <redacted>
  ✓ state        databases healthy
  ✓ threads      rollout files and state DB thread inventory agree

Configuration
  ✓ config       loaded
  ✓ auth         auth is configured
  ✓ mcp          no MCP servers configured
  ✓ sandbox      unrestricted fs + enabled network · approval Never

Updates
  ✓ updates      update configuration is locally consistent

Connectivity
  ✓ network      no proxy env vars
  ✓ websocket    connected (HTTP 101 Switching Protocols) · 15s timeout
  ✓ reachability active provider endpoints are reachable over HTTP

Background Server
  ✓ app-server   running (ephemeral mode)

18 ok · 1 notes · 0 warn · 0 fail

Remote Codex config was set to unrestricted filesystem / network enabled /
approval Never during debugging, then the remote app-server was restarted.

Local Codex App doctor

Running the bundled app binary:

/Applications/Codex.app/Contents/Resources/codex doctor --summary

Summary:

Codex Doctor v0.142.5 · macos-aarch64

Notes
   ↑ updates      0.143.0 available (current 0.142.5)
   ⚠ rollouts     1,255 active files · 1.12 GB on disk
   ⚠ sandbox      filesystem unrestricted · network enabled
   ✗ terminal     TERM=dumb - colors and cursor control are disabled

Configuration
  ✓ sandbox      unrestricted fs + enabled network · approval Never

Background Server
  ○ app-server   not running (ephemeral mode)

16 ok · 1 idle · 4 notes · 0 warn · 1 fail

The terminal note appears to come from running doctor non-interactively and does not prevent normal local Git operations.

Manual validations that pass

1. Content mirrors are aligned

A checksum-based rsync dry run excluding dependency/build/cache directories reports zero content diffs for all active mirrors:

repo-a content_diff_count=0
repo-b content_diff_count=0
repo-c content_diff_count=0
repo-d content_diff_count=0
repo-e content_diff_count=0

Ignored operational paths that are needed for local development were also checked separately:

repo-b-runtime-dir-a content_diff_count=0
repo-b-runtime-dir-b content_diff_count=0
repo-c-local-config content_diff_count=0
repo-c-private-files content_diff_count=0

Dependency/build artifacts were intentionally not copied from macOS to Linux. They were rebuilt natively on the SSH host instead.

2. Remote development dependencies are warmed

Commands run successfully on the SSH host:

repo-a: uv sync && bun install --frozen-lockfile
repo-d: uv sync
repo-e: uv sync
repo-b/subproject-a: bun install --frozen-lockfile
repo-c/subproject-a: corepack yarn install --immutable
repo-c/subproject-b: corepack yarn install --immutable

Git remained clean afterward in all checked repositories.

3. Manual Git worktree smoke tests pass on both machines

For each active repository, a temporary branch/worktree was created and removed manually on both local and remote:

LOCAL repo-a worktree_smoke=ok
LOCAL repo-b worktree_smoke=ok
LOCAL repo-c worktree_smoke=ok
LOCAL repo-d worktree_smoke=ok
LOCAL repo-e worktree_smoke=ok

REMOTE repo-a worktree_smoke=ok
REMOTE repo-b worktree_smoke=ok
REMOTE repo-c worktree_smoke=ok
REMOTE repo-d worktree_smoke=ok
REMOTE repo-e worktree_smoke=ok

Afterward:

LOCAL repo-a ## main...origin/main smoke_branches=0
REMOTE repo-a ## main...origin/main smoke_branches=0
...

Relevant log excerpts

Raw logs are not attached here because they may contain private local paths, thread previews, and repository names. These are sanitized excerpts from ~/Library/Logs/com.openai.codex/2026/07/09.

Repeated warnings while using remote SSH project/worktree flows:

warning [worktreeShellEnvironmentConfig] Failed to read worktree shell environment config
errorMessage="Failed to read app-server file: cat: /home/<remote-user>/Documents/code/repo-a/.git/codex-shell-environment.json: No such file or directory"
errorStack="Error: Failed to read app-server file: cat: /home/<remote-user>/Documents/code/repo-a/.git/codex-shell-environment.json: No such file or directory
    at Object.pull (/Applications/Codex.app/Contents/Resources/app.asar/.vite/build/src-CoIhwwHr.js:76:4473)"

Another warning observed during move-thread-to-host-worktree:

warning [git] git.command.complete
command="git -c core.hooksPath=/dev/null -c core.fsmonitor= config --worktree codex.localEnvironmentConfigPath __none__"
cwd=/home/<remote-user>/.codex/worktrees/<worktree-id>/repo-a
exitCode=128
failureReason=command_failed
hostId=remote-ssh-discovered:<ssh-host-alias>
requestKind=move-thread-to-host-worktree
source=move_to_host_worktree
stderrBytes=192

The same config --worktree codex.localEnvironmentConfigPath __none__ warning was also seen on a local Codex-managed worktree path.

Earlier observations while debugging

Before changing remote Codex permissions to unrestricted, an older remote thread could edit/check files but failed before shell startup or failed writing Git metadata:

bwrap: Can't mkdir /.git: Permission denied

and:

fatal: cannot lock ref 'refs/heads/work-3-smoke-test':
Unable to create '/home/<remote-user>/Documents/code/repo-a/.git/refs/heads/work-3-smoke-test.lock':
Read-only file system

After setting the remote Codex config to unrestricted filesystem/network and restarting the remote app-server, manual git worktree operations work. However, Codex App handoff still fails at the same UI step.

Steps to reproduce

  1. On macOS Codex App, configure an SSH host in Settings -> Connections.
  2. On both local and SSH host, have the same Git repository checked out:
  • local: /Users/<local-user>/Documents/Dev/code/repo-a
  • remote: /home/<remote-user>/Documents/code/repo-a
  1. Ensure both checkouts are clean and on the same branch/commit:
  • git status --short --branch
  • git rev-parse HEAD
  • git worktree list --porcelain
  1. Ensure the SSH host has Codex installed/authenticated and codex doctor --summary passes.
  2. Start or open a local Codex thread in the project.
  3. Make a tiny tracked file change, or leave the thread with no meaningful code changes.
  4. Use the Codex App handoff UI to hand off the thread to the SSH host.

Result

The handoff modal progresses through file transfer and worktree creation, then fails at:

Applying uncommitted changes to worktree

with:

Failed to continue on another host: Destination checkout is already using the handoff branch, and Codex could not switch it to a default branch

Related docs / issues checked

Docs used while configuring and validating:

Existing issues searched:

Additional note

There may also be a sidebar/history desync around remote threads: a remote thread could be opened directly by ID through app navigation but did not persist/reappear in the sidebar for the user. That may be separate from the handoff failure, but it happened while debugging this same remote SSH setup.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗