I was rereading the setup page one evening when a small section called "Install on network storage" stopped me. It describes a session that crashes with a Bus error in the middle of work.
My own setup is a single iMac at home, with no shared home directory. So I haven't hit this myself. Still, for anyone whose home lives on network storage and is mounted on several machines, it's the kind of trouble that arrives without warning. I'm writing down the official notes in a form you can run.
The short version
What I'd like to say first: the crash happens because the file a session is running gets removed from another machine, so what you need to stop is every update path, plus the habit of deleting old versions by hand.
My first misreading was that DISABLE_AUTOUPDATER would be enough. The docs say plainly that it isn't.
The symptom and why it happens
A running Claude Code reads parts of its executable from disk while it works, not only at startup. If that file is truncated or deleted and becomes unreadable, the session crashes. In a Linux shell it shows up as Bus error.
When the home directory is on network storage, an update on one machine can remove the file under a session running on another. A machine can't see processes on other machines, so "check for running processes before deleting" doesn't work either.
Two ways the file disappears
I split the docs' explanation into two paths.
| path | what happens |
|---|---|
| npm global upgrade | `npm install -g` deletes the previous binary in place. On shared storage, that removes the version other machines are still running. |
| Native installer cleanup | It removes old versions under `~/.local/share/claude/versions/`. It keeps the version the launcher points to, any version running on the same machine, and the two newest versions, and deletes the rest. |
The native cleanup only looks at its own machine. A session on another machine that is running an older version isn't protected.
Three levels of turning updates off
The settings differ in how far they reach.
| setting | stops | does not stop |
|---|---|---|
| `DISABLE_AUTOUPDATER` | The background update check | `claude update`, `claude install` |
| `DISABLE_UPDATES` | Every update path, manual ones included | Nothing (installs through your own tooling are separate) |
For shared storage the docs point to DISABLE_UPDATES. If even one person types the command, DISABLE_AUTOUPDATER alone lets the same thing happen.
Stop more than "automatic": stop every update that anyone can trigger by hand. That's the line I'd draw.
Where to put things
The docs' layout advice comes down to three points.
- Put the binary on each machine's local disk, for example through a Linux package manager or your own deployment tooling. The native installer's default
~/.local/share/claude/versions/and a per-user npm prefix both sit in the home directory. - Keep each version in its own directory, and install new versions next to the old ones instead of overwriting.
- Delete an old version only when you can say no machine is running it.
Two scripts I ran
The first checks whether the install location is on shared storage. It reads /proc/mounts and picks the mount that contains the path.
"""Check whether the Claude Code install location sits on shared storage (Linux)."""
import os
import sys
SHARED = {"nfs", "nfs4", "cifs", "smb3", "smbfs", "fuse.sshfs", "afs", "ceph", "glusterfs"}
def mount_of(path):
path = os.path.realpath(path)
best = ("/", "unknown")
with open("/proc/mounts") as f:
for line in f:
_, mp, fstype, *_ = line.split()
if (path == mp or path.startswith(mp.rstrip("/") + "/")) and len(mp) >= len(best[0]):
best = (mp, fstype)
return best
target = os.path.expanduser(sys.argv[1] if len(sys.argv) > 1 else "~/.local/share/claude")
probe = target
while not os.path.exists(probe) and probe != "/":
probe = os.path.dirname(probe) # if it does not exist yet, judge by the nearest existing parent
mp, fstype = mount_of(probe)
verdict = "shared storage: move the binary to local disk" if fstype in SHARED else "treated as local"
print(f"target={target}\nprobed={probe}\nmount={mp} type={fstype}\n=> {verdict}")In my Linux work environment the type came back as ext4, so the verdict was "local." If the path doesn't exist yet, it judges by the nearest existing parent. I haven't tried it on real shared storage, so I'd be glad if you could run it once in your own environment.
The second copies the official cleanup rule so you can see which versions survive. The version numbers are examples.
"""The documented cleanup rule: keep the launcher target, versions running on this machine, and the two newest."""
def key(v): return tuple(int(x) for x in v.split("."))
def survivors(installed, launcher_target, running_here):
newest_two = sorted(installed, key=key)[-2:]
return set(newest_two) | {launcher_target} | set(running_here)
installed = ["2.1.309", "2.1.313", "2.1.314", "2.1.316", "2.1.317"] # 例
keep = survivors(installed, launcher_target="2.1.317", running_here=["2.1.317"])
deleted = [v for v in installed if v not in keep]
print("survive:", sorted(keep, key=key))
print("deleted:", deleted)
for host, ver in {"machine B": "2.1.309", "machine C": "2.1.316"}.items():
print(f"{host} running {ver}:", "loses its binary" if ver in deleted else "fine")This is what it printed.
survive: ['2.1.316', '2.1.317']
deleted: ['2.1.309', '2.1.313', '2.1.314']
machine B running 2.1.309: loses its binary
machine C running 2.1.316: fineThis is a calculation that mirrors the docs' wording, not a reproduction of real deletion. Even so, seeing the numbers made it obvious that "keep the two newest" doesn't protect a machine still running an older version.
What I check on a single machine
As an indie developer working on one iMac, I'd have filed the shared-home story under someone else's problem. Rereading it, though, I realized the way to confirm an update switch is the same everywhere.
After setting it, run claude doctor and look at the Auto-updates line. If it still says enabled, the setting isn't doing its job. Per the docs, when DISABLE_AUTOUPDATER is in effect it reads disabled (set by env: DISABLE_AUTOUPDATER). I used to stop at writing the settings file and never looked at that line. In hindsight, having written the setting and having it take effect were two different things.
What to do next
As a first step, run the location check on one of the machines that share the home directory. If it reports shared storage, move the binary to local disk, set DISABLE_UPDATES, and switch to updating through your own deployment. That single change takes away the morning when a crashed session's work doesn't come back.