anthropics / anthropics/claude-code
Bash tool: ~/.claude is bind-mounted read-only with no way to opt out, so hook state and config-manager writes always fail with EROFS
- Langage dominant
- Python
- Étoiles
- 145k
- Forks
- 23.1k
- Métriques de merge des PR
- Métriques de PR en attente
Description
## Summary
On Linux, the Bash tool runs in a mount namespace where `~/.claude`, `~/.claude.json`
and each trusted repo's `.claude/` are bind-mounted **read-only**. Every write from Bash
into those paths therefore fails with `EROFS`, and there is no supported way to opt out:
- `"sandbox": { "enabled": false }` in `~/.claude/settings.json` does **not** remove it.
- The Bash tool's `dangerouslyDisableSandbox: true` does **not** remove it.
Meanwhile the **Write and Edit tools write to the same paths without any trouble**, so this
is not a policy boundary — it only blocks one of the two tool paths. That asymmetry is what
makes it costly: the restriction is invisible until a command fails, and the failure surfaces
as a bare `EROFS` with no mention of a mount.
## Evidence
Claude Code 2.1.236, native build, Linux 5.15 (Ubuntu), no managed settings.
From inside a Bash tool call:
```
$ grep -i claude /proc/self/mountinfo
... /home/USER/.claude/debug /home/USER/.claude/debug rw,nosuid,nodev,relatime ...
... /home/USER/.claude/ide /home/USER/.claude/ide rw,nosuid,nodev,relatime ... tmpfs
... /home/USER/.claude /home/USER/.claude ro,nosuid,nodev,relatime ...
... /home/USER/.claude.json /home/USER/.claude.json ro,nosuid,nodev,relatime ...
... /home/USER//.claude /home/USER//.claude ro,nosuid,nodev,relatime ...
```
`~/.claude/debug` and `~/.claude/ide` are rw submounts; everything else under `~/.claude` is ro.
Writing there fails identically with and without the sandbox override:
```
$ chezmoi apply ~/.claude/settings.json
chezmoi: .claude/settings.json: open /home/USER/.claude/.settings.jsonNNNNNNNN: read-only file system
# exit 1 — same result with dangerouslyDisableSandbox: true
```
The same one-line change applied through the **Edit tool** succeeded on the first try, and the
file on disk reflected it.
## Impact
1. **Hooks that persist their own state cannot be invoked from Bash.** A `PreToolUse` gate that
records "this was reviewed / this ticket was transitioned" under `~/.claude//state/`
works when the hook itself runs (Claude Code's own process), but the companion CLI that the
agent is supposed to run to *write* the marker fails every time. Users hit this as a hard
wall with no hint about the cause.
2. **`chezmoi apply` (and any config manager) can never target `~/.claude` from Bash**, so
declaratively-managed Claude configs need an out-of-band manual step on every change.
3. **Auto mode actively steers into it.** While auto mode is active the agent is instructed to
prefer `sed`/heredocs over the Write and Edit tools for file changes — precisely the path
that cannot work for these paths. The result is a repeating try → `EROFS` → switch-to-Edit
round trip, several times per session.
## What would help (any one of these)
- **Document the mount** and expose a supported, writable location for hook/CLI state (an
`XDG_STATE_HOME`-style path, or making `~/.claude/state` an rw submount like `debug`/`ide`).
- **Honor the existing escape hatches**: either `sandbox.enabled: false` or
`dangerouslyDisableSandbox: true` lifting the config-dir bind mount would be unsurprising,
given both already read as "turn this protection off".
- **At minimum, fail with a message that names the cause** — e.g. "`~/.claude` is mounted
read-only for Bash; use the Write/Edit tools" — instead of a raw `EROFS` that gives the agent
nothing to act on.
Related but distinct: #78162 is the same error text from one-hop symlink resolution during
Claude Code's own atomic settings write, not from the Bash mount namespace.
Guide de contribution
Aucun guide de contribution indexé pour ce dépôt
Piste de recherche
Start by finding the Bash tool sandbox or mount-namespace setup and where ~/.claude, ~/.claude.json, and repo .claude/ paths are bind-mounted. Reproduce on Linux with Claude Code 2.1.236 using /proc/self/mountinfo and a write such as chezmoi apply. Done means either the opt-out/writable-state behavior works or the Bash failure clearly explains the read-only mount.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- bash, linux, python
- Domaine
- cli, developer-experience, security
- Type d'issue
- Bug
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Activité
- Active
- Clarté
- Plutôt claire
- Accessibilité débutants
- 45/100