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
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 doctorfrom 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, build25F80 - 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/removeworks 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
- On macOS Codex App, configure an SSH host in Settings -> Connections.
- 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
- Ensure both checkouts are clean and on the same branch/commit:
git status --short --branchgit rev-parse HEADgit worktree list --porcelain
- Ensure the SSH host has Codex installed/authenticated and
codex doctor --summarypasses. - Start or open a local Codex thread in the project.
- Make a tiny tracked file change, or leave the thread with no meaningful code changes.
- 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:
- Remote SSH host setup: https://developers.openai.com/codex/remote-connections#connect-to-an-ssh-host
- Worktrees / Handoff behavior: https://developers.openai.com/codex/app/worktrees
- Troubleshooting / logs: https://developers.openai.com/codex/app/troubleshooting
Existing issues searched:
- Exact search for
"Failed to continue on another host" handoff: no results - Exact search for
"Destination checkout is already using the handoff branch": no results - Exact search for
"Applying uncommitted changes" handoff: no results - Potentially related but not the same: https://github.com/openai/codex/issues/26017
- Potentially related remote SSH environment issue: https://github.com/openai/codex/issues/23648
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.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗