[BUG] Cowork sessions ignore user hooks and managed settings — sandbox platform mismatch breaks all settings resolution
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Cowork (local-agent-mode) sessions silently ignore all three settings sources: user settings (~/.claude/settings.json), managed/MDM settings (/Library/Application Support/ClaudeCode/managed-settings.json), and environment variable overrides. This means user-defined hooks never fire, enterprise managed policies are not enforced, and env-based configuration (e.g. CLAUDE_CODE_EFFORT_LEVEL) has no effect.
This is distinct from #27398 (plugin hooks via --setting-sources user). That issue covered plugin-scoped hook discovery being excluded by the --setting-sources flag. This issue covers three additional, independent root causes that affect all settings — not just plugin hooks — and persist even if --setting-sources were fixed.
Root Cause 1: User settings file doesn't exist in the sandbox
The sandbox sets CLAUDE_CONFIG_DIR=/sessions/<name>/mnt/.claude. In cowork mode, the binary looks for cowork_settings.json (via the WK5() / getSettingsFilename() function that checks isCowork()). This file does not exist in the sandbox — only .claude.json is present.
The user's actual ~/.claude/settings.json on the macOS host is never mounted into the VM.
Verified from inside the sandbox:
$ echo $CLAUDE_CONFIG_DIR
/sessions/eloquent-upbeat-albattani/mnt/.claude
$ ls $CLAUDE_CONFIG_DIR/settings.json
No such file or directory
$ ls $CLAUDE_CONFIG_DIR/cowork_settings.json
No such file or directory
Root Cause 2: Managed settings path resolves to wrong location (platform mismatch)
The managed settings directory is resolved by process.platform:
// Reconstructed from compiled binary
function getManagedSettingsDir() {
switch (getPlatform()) {
case "macos": return "/Library/Application Support/ClaudeCode";
case "windows": return "C:\\Program Files\\ClaudeCode";
default: return "/etc/claude-code"; // Linux falls here
}
}
The cowork sandbox is a Linux VM (Ubuntu 22.04 aarch64), so process.platform is linux, and the binary looks for /etc/claude-code/managed-settings.json. This path does not exist in the sandbox. The macOS host path (/Library/Application Support/ClaudeCode/) is never consulted.
Note: CLAUDE_CODE_HOST_PLATFORM=darwin is set as an env var, but the binary uses process.platform (which is linux), not this env var, for path resolution.
Verified from inside the sandbox:
$ uname -s
Linux
$ ls /etc/claude-code/
No such file or directory
$ ls /Library/
No such file or directory
$ echo $CLAUDE_CODE_HOST_PLATFORM
darwin
Root Cause 3: User environment variables are not forwarded into the sandbox
The sandbox receives a curated set of env vars (CLAUDE_CODE_IS_COWORK, CLAUDE_CONFIG_DIR, OAuth tokens, proxy ports, etc.), but user-set environment variables like CLAUDE_CODE_EFFORT_LEVEL from the macOS host are not forwarded.
$ echo $CLAUDE_CODE_EFFORT_LEVEL
(empty)
This means the documented workaround from #34428 (CLAUDE_CODE_EFFORT_LEVEL=max in settings.json env block) doesn't work for cowork — settings.json isn't loaded (Root Cause 1), and even if set in the host shell, the env var isn't forwarded (Root Cause 3).
Impact
| Settings Source | Interactive CLI | Headless (-p) | Cowork | Root Cause |
|---|---|---|---|---|
| ~/.claude/settings.json hooks | Fire | Fire | Silent no-op | Config dir has no settings file |
| Managed settings (MDM) | Loaded | Loaded | Silent no-op | Platform mismatch → wrong path |
| CLAUDE_CODE_EFFORT_LEVEL env | Works | Works | Ignored | Env not forwarded to sandbox |
| .claude.json (OAuth/flags) | Loaded | Loaded | Loaded | ✅ Mounted via bindfs |
Enterprise concern: Managed settings are designed for policy enforcement via MDM profiles. Having them silently ignored in cowork means enterprise admins cannot enforce hooks, permission rules, or other policies in cowork sessions — a compliance gap.
What Should Happen?
- User hooks from
~/.claude/settings.jsonshould be mounted/copied into the sandbox ascowork_settings.json(or the binary should read from a host-provided path) - Managed settings from the macOS host should be bind-mounted into the sandbox at
/etc/claude-code/managed-settings.json(the Linux-expected path), since the binary already knows how to load from there - User env vars relevant to Claude Code (at minimum
CLAUDE_CODE_EFFORT_LEVEL) should be forwarded into the sandbox
Error Messages/Logs
No errors — all three failures are silent. Settings resolution finds no file and returns empty/default. This is part of the problem: there's zero indication that settings are being ignored.
Steps to Reproduce
- Add hooks to
~/.claude/settings.jsonon the macOS host (e.g., aPostToolUsehook that writes to a log file) - Confirm the hooks fire in an interactive
claudeCLI session - Start a Cowork session in Claude Desktop
- Trigger the same hook event (e.g., use a tool)
- Observe that hooks never fire — no log file is written, no hook output appears
- Optionally verify from inside the sandbox (if you can get shell access) that
$CLAUDE_CONFIG_DIR/cowork_settings.jsonand/etc/claude-code/managed-settings.jsondon't exist
Claude Model
claude-opus-4-6
Is this a regression?
No, this never worked
Last Working Version
_No response_
Claude Code Version
Cowork VM binary at /usr/local/bin/claude (version embedded in Bun-compiled binary, matches latest Claude Desktop release)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Other
Additional Information
Related issues:
- #27398 — Cowork plugin hooks not firing due to
--setting-sources user(closed as duplicate, different root cause from this issue) - #32364 — OTel config not available in sandboxed environments (same underlying problem: settings.json inaccessible in sandbox)
- #34428 — Effort level not persisted (workaround via settings.json
envblock doesn't work in cowork)
Key environment variables in the cowork sandbox:
CLAUDECODE=1
CLAUDE_CODE_IS_COWORK=1
CLAUDE_CODE_ENTRYPOINT=local-agent
CLAUDE_CONFIG_DIR=/sessions/<name>/mnt/.claude
HOME=/sessions/<name>
CLAUDE_CODE_HOST_PLATFORM=darwin
SANDBOX_RUNTIME=1
Sandbox architecture: Linux VM (Ubuntu 22.04 aarch64) using bubblewrap (bwrap) for process isolation. Host directories are selectively bind-mounted via bindfs FUSE mounts with controlled permissions. The .claude/ directory is mounted read-write but only contains .claude.json — no settings.json or cowork_settings.json.
This issue has 15 comments on GitHub. Read the full discussion on GitHub ↗