Cloud multi-repo sessions never load repo .claude/settings.json (hooks silently don't fire), and CLAUDE_PROJECT_DIR is empty
Environment
- Claude Code on the web (claude.ai/code), cloud sandbox sessions
- Repo has
.claude/settings.jsonwithSessionStarthooks (context injection) - Same configuration works correctly in local CLI sessions and in single-repo cloud sessions
Summary
Two related problems observed in multi-repo cloud sessions (a session started with two or more repositories):
- The repo's
.claude/settings.jsonis never loaded. Project settings discovery appears to be cwd-based, and in multi-repo sessions the cwd is the parent directory (/home/user), not a repo root — so<repo>/.claude/settings.jsonis never discovered. The multi-repo registration mechanism does load the repo'sCLAUDE.md,.claude/rules/,.claude/skills/, and plugins (which live at their own paths), which makes the failure easy to misdiagnose: most of.claude/visibly works, so users assume hooks should too. But anything defined only insettings.json— hooks being the most visible — silently doesn't apply.
CLAUDE_PROJECT_DIRis set to an empty string in cloud sessions. Any hook command using the documented${CLAUDE_PROJECT_DIR}pattern (or a${CLAUDE_PROJECT_DIR:-.}fallback) resolves relative to the wrong directory when cwd is outside the repo, producing a silent "No such file" failure.
Steps to reproduce
- Add to
<repo>/.claude/settings.json:
``json`
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{"type": "command", "command": "bash \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/inject.sh"}
]
}
]
}
}
inject.sh` echoes a recognizable marker to stdout.
where
- Start a single-repo cloud session with that repo → the marker appears in context. ✅
- Start a multi-repo cloud session including that repo → the marker never appears; the hook is not registered at all. ❌
- Inside the multi-repo session,
echo "[$CLAUDE_PROJECT_DIR]"prints[](empty, not unset), andpwdis/home/userwhile repos live at/home/user/<repo>.
Expected behavior
- Repo
.claude/settings.jsonis applied in multi-repo sessions the same way CLAUDE.md / rules / skills / plugins are (or the docs state explicitly that repo settings are single-repo-session only). CLAUDE_PROJECT_DIRpoints at the repo the hook was loaded from (per the hooks documentation: "the absolute path to the project root directory"), or is left unset rather than empty so${CLAUDE_PROJECT_DIR:-fallback}works.
Actual behavior
- In multi-repo sessions, no hook from any repo's
.claude/settings.jsonfires. Only platform-level hooks (~/.claude/launcher-settings.json) run. CLAUDE_PROJECT_DIRis""in cloud sessions, so the documented substitution pattern silently resolves relative to/home/user.
Impact
Sessions that rely on SessionStart context injection (persona/config/memory bootstrapping) start silently degraded — no error is surfaced, the model behaves as though the configuration doesn't exist. Presumably other settings.json-only configuration (e.g. permissions allow/deny rules) is dropped in multi-repo sessions as well, though hooks are where we verified it.
Workaround
An environment Setup script can bridge the gap by writing the hooks into the user-level seat (which is empty in cloud sandboxes) with absolute paths:
mkdir -p /root/.claude
cat > /root/.claude/settings.json << 'EOF'
{
"hooks": {
"SessionStart": [
{
"matcher": "startup|clear|compact",
"hooks": [
{"type": "command", "command": "bash /home/user/<repo>/.claude/hooks/inject.sh", "timeout": 5000}
]
}
]
}
}
EOF
This works, but hardcodes the clone path and must be maintained per environment.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗