[BUG] Cowork sessions ignore user hooks and managed settings — sandbox platform mismatch breaks all settings resolution

Open 💬 15 comments Opened Mar 29, 2026 by gmnbs

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?

  1. User hooks from ~/.claude/settings.json should be mounted/copied into the sandbox as cowork_settings.json (or the binary should read from a host-provided path)
  2. 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
  3. 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

  1. Add hooks to ~/.claude/settings.json on the macOS host (e.g., a PostToolUse hook that writes to a log file)
  2. Confirm the hooks fire in an interactive claude CLI session
  3. Start a Cowork session in Claude Desktop
  4. Trigger the same hook event (e.g., use a tool)
  5. Observe that hooks never fire — no log file is written, no hook output appears
  6. Optionally verify from inside the sandbox (if you can get shell access) that $CLAUDE_CONFIG_DIR/cowork_settings.json and /etc/claude-code/managed-settings.json don'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 env block 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.

View original on GitHub ↗

This issue has 15 comments on GitHub. Read the full discussion on GitHub ↗