Config save creates lock/temp files in ~/ which breaks sandboxed environments
Summary
Claude Code's config save mechanism creates ~/.claude.json.lock and ~/.claude.json.tmp.<pid>.<timestamp> in the user's home directory. This prevents Claude Code from running inside filesystem sandboxes (like Landlock on Linux) that can grant write access to ~/.claude.json but cannot allow creating arbitrary new files in ~/.
Details
The saveConfigWithLock function acquires a lock at ${configPath}.lock and safeWriteFileAtomically writes to ${configPath}.tmp.${pid}.${timestamp} before renaming. Since configPath is ~/.claude.json, both files are created directly in ~/.
Filesystem sandboxes like Landlock (Linux) can grant write access to a specific file but cannot grant permission to create new files in a directory without opening the entire directory for writes. On Linux, Landlock is strictly allow-list — there is no way to express "allow creating files in ~/ but deny write to subdirectories."
This means any sandbox that protects ~/ while allowing ~/.claude.json writes will break when Claude Code tries to save config. The session crashes with:
EACCES: permission denied, open '/home/user/.claude.json'
The atomic write function does have a fallback to direct writeFileSync, but the lock file creation happens before the write and has no fallback.
Suggested fix
Create lock and temp files in ~/.claude/ instead of ~/:
~/.claude/.claude.json.lock (instead of ~/.claude.json.lock)
~/.claude/.claude.json.tmp.<pid> (instead of ~/.claude.json.tmp.<pid>.<ts>)
Or better yet, as part of the XDG migration (#1455), move the config file itself to ~/.claude/config.json or $XDG_CONFIG_HOME/claude/config.json, which would naturally place the lock and temp files in a directory the application already owns.
Context
This was discovered while running Claude Code inside nono, a capability-based sandbox. The nono claude-code profile grants read+write to ~/.claude.json and ~/.claude/, but sessions crash after a few minutes when config save is first triggered. Short operations like claude -v work because they exit before any config save.
Environment
- Claude Code 2.1.63
- Linux 6.19.5, Landlock ABI v5
- nono v0.8.0
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗