# Letting Codex Agents Commit: Making .git Writable in the workspace-write Sandbox

By Corey J. Gallon · 2026-07-22 · https://gallon.me/letting-codex-agents-commit-making-git-writable-in-the-workspace-write-sandbox

---

Codex CLI's `workspace-write` sandbox lets the agent edit anything in your repo -- except commit. Every `git commit` dies with:

```text
fatal: Unable to create '/path/to/repo/.git/index.lock': Read-only file system
```

This is deliberate. On Linux, Codex's bubblewrap sandbox mounts your writable roots read-write, then **re-applies `.git` (plus `.codex` and `.agents`) as read-only** on top. The security rationale is sound: a writable `.git/hooks` would let the agent plant a hook that executes *outside* the sandbox the next time you run git yourself.

But if you're already running with `--ask-for-approval never` -- YOLO mode -- you've made that trust decision, and an agent that can't commit its own work is a constant irritation. There's no official toggle: no `allow_git_writes` option exists anywhere in the codebase, and the open issues asking for one ([#15505](https://github.com/openai/codex/issues/15505), [#12280](https://github.com/openai/codex/issues/12280), [#14338](https://github.com/openai/codex/issues/14338)) have no maintainer response.

## The trick: name the `.git` path itself

The obvious fixes don't work. Adding the *repo root* to `sandbox_workspace_write.writable_roots` fails because the `.git` protection is applied per writable root -- a writable parent still gets a read-only `.git` carved out of it ([#15505](https://github.com/openai/codex/issues/15505)). Passing extra directories with `--add-dir` fails because the read-only mount is applied after the command-line write dirs, so it wins ([#14338](https://github.com/openai/codex/issues/14338)).

But reading the sandbox policy source ([`codex-rs/protocol/src/permissions.rs`](https://github.com/openai/codex/blob/main/codex-rs/protocol/src/permissions.rs)), the carveout is added by a function named `append_default_read_only_path_if_no_explicit_rule`. The name says it all: if an **explicit rule already covers the exact `.git` path**, the read-only protection is skipped.

So point `writable_roots` at the `.git` directory itself:

```bash
codex exec --sandbox workspace-write \
  -c 'sandbox_workspace_write.writable_roots=["/path/to/repo/.git"]' \
  "commit your work"
```

Verified on codex-cli 0.144.6: without the flag, the commit fails with the read-only error above; with it, the commit lands -- confirmed in `git log`, not just the agent's self-report.

## Wiring it into a shell function

The writable path is per-repo, so compute it at invocation time. My `yolo-codex` wrapper now does:

```zsh
# Make .git writable inside the workspace-write sandbox so the agent can
# commit. Codex mounts .git read-only unless an explicit writable_roots
# entry names the .git path itself. Includes the common gitdir so linked
# worktrees can commit too.
local -a git_writable=()
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
  local git_dir git_common_dir
  git_dir=$(git rev-parse --absolute-git-dir)
  git_common_dir=$(git rev-parse --path-format=absolute --git-common-dir)
  if [[ "$git_dir" == "$git_common_dir" ]]; then
    git_writable=(-c "sandbox_workspace_write.writable_roots=[\"$git_dir\"]")
  else
    git_writable=(-c "sandbox_workspace_write.writable_roots=[\"$git_dir\",\"$git_common_dir\"]")
  fi
fi

codex --ask-for-approval never --sandbox workspace-write "${git_writable[@]}" "$@"
```

Two details worth the extra lines:

- **Linked worktrees.** In a `git worktree` checkout, `--absolute-git-dir` points at the per-worktree gitdir, but commits also write objects and refs into the *common* gitdir back in the main repo. Both paths need to be writable. Tested: a commit from inside a linked worktree works with both entries, and a plain repo needs only the one.
- **The `-c` flag sets only `writable_roots`.** Anything else you have under `[sandbox_workspace_write]` in `~/.codex/config.toml` (like `network_access = true`) is untouched.

Outside a git repo, the array stays empty and the function behaves exactly as before.

## Caveats

- **This is undocumented behavior.** The explicit-rule exemption is an implementation detail of the sandbox policy, not a documented feature. A future Codex release could re-protect `.git` unconditionally -- if agent commits start failing after an upgrade, this is the first thing to re-check.
- **You're removing a real protection, not working around a bug.** A writable `.git` means a writable `.git/hooks`, and hooks run unsandboxed when *you* next invoke git. If you're not already running approval-free, think twice.
- **The blunt alternative is `--sandbox danger-full-access`**, which trades the entire filesystem sandbox to fix one directory. Carving out `.git` keeps everything else protected.

Tested on codex-cli 0.144.6, Linux (bubblewrap sandbox).
