---
title: "How to stop an agent editing a file someone else is changing · Cork"
description: "Block an AI coding agent from editing a file another session is changing: a tested Claude Code PreToolUse lock hook, Cursor and Codex equivalents, and limits."
canonical: "https://corkcli.com/blog/stop-agent-editing-file-someone-else-is-changing"
last_updated: "2026-11-14"
published: "2026-10-03"
author: "Kevin Vera"
---

# How to stop an agent editing a file someone else is changing

Block an AI coding agent from editing a file another session is changing: a tested Claude Code PreToolUse lock hook, Cursor and Codex equivalents, and limits.

By Kevin Vera · October 3, 2026 · [Guides](https://corkcli.com/blog/c/guides) · 7 min read

To stop an AI coding agent from editing a file someone else is changing, put a check in front of the agent's edit tool: a hook that runs before every edit, looks up whether another session has claimed that file, and blocks the edit with a reason if it has. Claude Code, Cursor, and Codex all support pre-tool hooks that can block, so a small lock script gets you most of the way on one machine. The harder parts are locks that go stale, people who edit outside any agent, and teammates on other machines.

## Why agents overwrite each other

Coding agents edit files directly on disk. Nothing in git or the file system stops two writers: the last save wins. Worktrees avoid the problem by giving each agent its own copy, at the cost of finding the conflict later at merge time. Claude Code's own agent teams docs, where teammates share a checkout, state the risk plainly: "Two teammates editing the same file leads to overwrites."

So if agents share a checkout, or you want to stop two worktrees from producing conflicting edits to the same file, you need a gate before the write.

## How blocking hooks work in Claude Code

A `PreToolUse` hook runs before a tool call and can stop it. From the hooks reference: "Exit code 2 blocks the tool call. The tool never executes," and the blocking message comes from your stderr text. The hook receives JSON on stdin, including:

```json
{
  "session_id": "abc123",
  "cwd": "/home/user/my-project",
  "hook_event_name": "PreToolUse",
  "tool_name": "Edit",
  "tool_input": { "file_path": "/home/user/my-project/src/app.ts" }
}
```

A matcher of `"Edit|Write"` limits the hook to the edit and write tools.

## A file-claim hook you can use today

This script gives each session a 10-minute claim on every file it edits and blocks any other session that tries to edit a claimed file. Claims live in the repository's shared git directory, so they work across all worktrees of the same repo: the same file in two worktrees gets the same lock. It needs `bash`, `jq`, and a `git` recent enough to support `rev-parse --path-format`.

Save it as `.claude/hooks/file-lock.sh` and make it executable (`chmod +x`):

```bash
#!/usr/bin/env bash
# Claim each file this session edits for 10 minutes; block other sessions meanwhile.
input=$(cat)
session=$(printf '%s' "$input" | jq -r '.session_id')
cwd=$(printf '%s' "$input" | jq -r '.cwd')
file=$(printf '%s' "$input" | jq -r '.tool_input.file_path // empty')
[ -z "$file" ] && exit 0

# Same key for the same file in every worktree of this repo
root=$(git -C "$(dirname "$file")" rev-parse --show-toplevel 2>/dev/null || echo "$cwd")
rel="${file#"$root"/}"
locks="$(git -C "$root" rev-parse --path-format=absolute --git-common-dir)/agent-locks"
mkdir -p "$locks"
lock="$locks/$(printf '%s' "$rel" | cksum | cut -d' ' -f1)"

now=$(date +%s); ttl=600
if [ -f "$lock" ]; then
  read -r owner since < "$lock"
  if [ "$owner" != "$session" ] && [ $((now - since)) -lt "$ttl" ]; then
    echo "$rel is being edited by another session (claimed $((now - since))s ago). Work on other files, or wait and re-read it." >&2
    exit 2
  fi
fi
printf '%s %s\n' "$session" "$now" > "$lock"
exit 0
```

Register it in `.claude/settings.json`, using the exec form the hooks docs recommend for path placeholders:

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/file-lock.sh",
            "args": []
          }
        ]
      }
    ]
  }
}
```

Run `/hooks` in Claude Code to confirm it is registered. We tested the script with two sessions in two worktrees of one repo: the first edit claims the file, the second session's edit to the same file exits 2 with the message, and the first session keeps editing freely. Every edit refreshes the claim, so a session that stops editing a file releases it after 10 minutes.

The error text matters: the agent reads it. Telling it to "work on other files, or wait and re-read it" steers it to adapt rather than retry blindly. Re-reading matters because the other session's version is the one the agent must build on.

## The same idea in Cursor and Codex

**Cursor** reads hooks from `.cursor/hooks.json` (project) or `~/.cursor/hooks.json` (user), with a required `"version": 1`. Its `preToolUse` hook is a permission hook that can return allow, deny, or ask, and exit code 2 from a script blocks the action:

```json
{
  "version": 1,
  "hooks": {
    "preToolUse": [
      { "command": "./scripts/file-lock-cursor.sh" }
    ]
  }
}
```

Cursor's input JSON differs from Claude Code's, so adapt the field names in the script to Cursor's hook schema.

**Codex** supports hooks in `hooks.json` or inline `[hooks]` tables in `config.toml`, at `~/.codex/` or `<repo>/.codex/`, including `PreToolUse`. Hooks are on by default. Again, check Codex's input fields before reusing the script.

## Limits of a do-it-yourself lock

The script is a useful guard, but know where it stops:

- **One machine only.** Locks live in the local git directory. A teammate's agent on another laptop never sees them.
- **Agents only.** A person editing in their editor goes through no hook. Ask people to commit or stash before handing files to agents, or keep agents in their own worktrees.
- **Whole files, not code.** Two agents changing different functions in a large file block each other needlessly, while an agent renaming a function in one file and another calling it from a second file are not blocked at all.
- **Best effort.** The check and the write are not atomic, so two edits in the same instant can both pass. Stale claims from crashed sessions hold for up to the TTL.
- **It blocks, it does not inform.** The blocked agent knows the file is busy, not what the other session is changing in it.

For files that must never be edited concurrently (binary assets, for example), Git LFS has real server-side locks: `git lfs lock` sets a path as locked "with the intention of blocking attempts by other users to update the given path," and LFS verifies that pushes do not modify files locked by others. That check happens at push time, not before an agent edits.

## How Cork helps

Cork's [write gate](https://corkcli.com/blog/write-gate) is this idea built to cover the gaps above. Cork is the coordination layer for multiplayer coding agents: it keeps Claude Code, Codex and Cursor agents, on one machine or across a team's machines, from overwriting each other on one codebase, and hands each agent what the others already learned.

For this problem specifically:

- **Write gate:** an edit against code another agent is changing right now is held until your agent has their version, so the blocked agent continues from the current code instead of guessing.
- **Live awareness:** when another agent changes code yours depends on (a rename, a new signature), your agent hears it on its next step, which covers the cross-file case a file lock misses.
- **Across machines:** on the paid plan, agents across the team see each other, not just the agents on your laptop.
- **No scripts to maintain:** hooks in Claude Code, Codex and Cursor run the protocol with no extra model calls.

Install it once for every repo on the machine:

```bash
curl -fsSL https://corkcli.com/install.sh | sh
```

## Frequently asked questions

### Can Claude Code lock a file?

Not by itself. You can add a `PreToolUse` hook on `Edit|Write` that exits with code 2 when another session holds a claim, which blocks the edit and shows Claude your reason.

### How do I block an AI agent from editing a specific file?

For a fixed list of files, a `PreToolUse` hook that checks `tool_input.file_path` against the list and exits 2 is enough. For files someone else is currently editing, use a claim-based hook like the one above or a write gate.

### Does git prevent two people editing the same file?

No. Git merges or reports conflicts after the fact. Git LFS can lock LFS-tracked files and reject pushes that modify files someone else locked.

### Do worktrees stop agents from overwriting each other?

They stop agents from overwriting each other's uncommitted files during work. The conflicting edits still meet at merge time.

## Sources

- <https://code.claude.com/docs/en/hooks>
- <https://code.claude.com/docs/en/agent-teams>
- <https://cursor.com/docs/agent/hooks>
- <https://learn.chatgpt.com/docs/hooks>
- <https://git-scm.com/docs/git-rev-parse>
- <https://github.com/git-lfs/git-lfs/blob/main/docs/man/git-lfs-lock.adoc>

## Related reading

- [Why AI agents re-read the same files, and how to stop it](https://corkcli.com/blog/why-ai-agents-reread-same-files): Why Claude Code, Codex and Cursor agents keep re-reading the same files, and how to stop it: specific prompts, lean context, symbol lookups and briefings.
- [How to stop Claude Code agents from overwriting each other's changes](https://corkcli.com/blog/stop-claude-code-agents-overwriting-changes): Why parallel Claude Code agents overwrite each other's edits, and how to stop it with worktrees, file ownership, deny rules, PreToolUse hooks and a write gate.
- [Pre-commit checks for code written by AI agents](https://corkcli.com/blog/pre-commit-checks-ai-generated-code): Pre-commit checks for AI-written code: git hooks, the pre-commit framework, secret scanning, and agent hooks in Claude Code, Codex and Cursor.
- [Codex hooks and Cursor hooks: how to use them for team coordination](https://corkcli.com/blog/codex-cursor-hooks-team-coordination): How Codex and Cursor hooks work as of October 2026, where the config lives, how to block or brief an agent, and how to use hooks to coordinate a team's agents.

[All articles](https://corkcli.com/blog.md) · [Cork in Markdown](https://corkcli.com/index.md) · [llms.txt](https://corkcli.com/llms.txt)

This page in HTML: https://corkcli.com/blog/stop-agent-editing-file-someone-else-is-changing
