You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug]: Per-account Claude folder created with no links to ~/.claude for one account — plugins missing and session history stored outside ~/.claude/projects #33170
After Orca auto-updated from 1.4.226 to 1.4.232 (macOS, arm64), Orca created per-account Claude folders under ~/Library/Application Support/orca/claude-profiles/<account id>/home and launched Claude with CLAUDE_CONFIG_DIR pointing there.
We have five Claude accounts in Orca. For four of them, the account home folder contained 13 symlinks back to ~/.claude (projects, session-env, file-history, shell-snapshots, todos, paste-cache, tasks, plans, transcripts, sessions, history.jsonl, plugins, skills).
For one account — the most recently added one (added in Orca the day before the update) — the home folder was created about 28 minutes after the others with zero symlinks. Orca's logs did not show why.
Impact
Every Claude session that ran under that account:
Had no plugins: /mcp listed only two servers. Plugin-provided MCP servers (Linear, GitHub, Notion, Slack, Figma, context7) were missing. claude --debug-file showed Plugin "linear" not cached … plugin-cache-miss.
Wrote its session history inside the account folder instead of ~/.claude/projects. Tools that read ~/.claude/projects could not see those sessions, and ListAgents did not list them, so other sessions could not message them.
We had ten sessions affected over about 80 minutes. We downgraded to 1.4.224 (the last release without per-account folders) and merged the stranded history back into ~/.claude/projects. The per-account history continued the original session files (no overlapping uuids; parentUuid chains continue from the original file), so appending to the original files restored them.
Expected
Every per-account home gets the same shared links, including accounts added shortly before the per-account feature first runs. If the links cannot be created, Orca should report it rather than launching Claude in an empty config dir.
We checked the commits under src/main/claude-accounts between v1.4.232 and v1.4.239 and did not find a change for this, so we have not upgraded yet.
Notes
We do not know the root cause. The only difference we could see was that the account was the newest one and its folder was provisioned later than the others.
Dug through the profile-setup chain on v1.4.232 to map how an account folder can come to exist with zero symlinks and no log line. The code has a designed-in window that matches your timeline exactly, plus a reason it would never self-heal. Three checks on your machine can confirm or kill it.
The window. Setup is the only thing that creates the 13 links, and it runs in two shapes: awaited in prepareLaunch when the marker (claude-profiles//profile.json — one level ABOVE home) is missing, and in the background from publish()/terminalEnv once the login-shell env has resolved. But terminalEnv deliberately returns pointer-only env BEFORE envResolved, and publish() writes the account home into the pointer file before any setup has run — its own comment says: "Why even a missing or covered folder: setup creates it without a login, so a sign-in, or Claude's own first run, signs in there." So the design explicitly lets Claude land in a folder Orca has not set up yet: a pane opened early after the update (env not yet resolved), with the pointer already naming your fifth account, launches claude → the shell function reads the pointer → CLAUDE_CONFIG_DIR= → Claude creates the folder itself on first run. That produces exactly your observation: home created ~28 min after the others (first use of that account, not the migration wave), zero symlinks (Orca's setup never ran), and zero Orca log lines (Orca never touched it).
Why it never heals. Background setup only fires for routedProfile() — the globally routed account. The marker-based awaited setup only runs in prepareLaunch's launch preparation. So if the fifth account never becomes the routed profile in a session where envResolved is true (e.g. you use it through panes that inherited the early pointer, while another account is the saved selection), setup never executes for it, the marker stays absent, and Claude keeps writing real directories (your impact #2 — sessions inside the account folder instead of ~/.claude/projects — is the fingerprint: on the four good accounts projects is a symlink; on the broken one it should be a REAL directory).
Three checks that would confirm:
Does claude-profiles//profile.json exist? (Prediction: absent for the fifth, present for the other four.)
Inside the fifth's home, is projects a real directory with session data (not a symlink)? Same for sessions.
Grep your Orca logs across the whole period (not just around creation) for "Account setup was incomplete" and "Account setup failed" — prediction: nothing for the fifth account, i.e. setup never even attempted-and-failed.
If that holds, the fix shape is at the routing layer, not the link layer: the pointer file (or the claude shell function) should treat a marker-less home as "not ready" — either block the pointer write until setup completes, or have the shell function fall back to the user's own config dir when the pointed-at folder has no marker. Happy to build the failing test and PR once the checks confirm which side of the race your machine hit.
#33479 (merged) fixes one cause we could reproduce: if Claude runs in a brand-new account before Orca's background setup finishes, Claude creates its own plugins/ folder and setup used to leave it unlinked, so plugins showed as "not cached". New accounts now merge and link it on first setup. Accounts that already hit this don't heal automatically: delete claude-profiles/<id>/home/plugins and start Claude again. We couldn't reproduce the state where no shared folders were linked at all on current main. If you still see that on the next build, could you share your Orca version and OS, and a listing of that account's home folder (names only, ls -la)?
The reporter has been quiet for 48h, so I kept digging on the window my analysis left open — the part #33479 doesn't cover (it fixes the healing side: first setup now adopts folders Claude made; it does not change when setup gets a chance to run). While scoping a fix I hit what looks like a real design tension that's worth a maintainer call before anyone builds the "treat a marker-less home as not ready" variant:
An unconditional marker gate in the claude shell function would break the deliberate flow it currently implements: the function creates a missing home on purpose (mkdir -p -m 700, header comment "Create account homes without a login silently") so that a newly added account's first run signs in inside that account's folder before setup has completed — and #33479's first-setup merge exists precisely to adopt what Claude writes there. Gating on the marker would send that first run to the user's own config dir instead, i.e. the login lands in the wrong place. So the naive routing-layer gate is not actually safe.
The narrower window my analysis named — pointer already naming an account whose setup never fires because background setup only runs for the routed (saved-selection) profile, while the pane's pointer can name a different account — still seems open, and it doesn't need the shell function to change. Two candidates that leave the first-run design intact:
Make background setup also cover the account a live pointer names when it differs from the saved selection and has no marker (the pointer file already tells us which home needs adopting), or
Both stay inside the existing marker semantics ("missing marker = setup hasn't run") and neither touches the shell function bytes. Happy to build the failing test and PR for whichever direction you prefer — the repro harness in claude-shell-function.test.ts already runs real shells, so the no-setup-fires scenario can be expressed there or next to publish()'s tests. If the reporter's three checks ever come back, they'd confirm which account hit this window, but the window itself is code-visible either way.
Activity
eatmoreduck commentedon Oct 24, 2026
Dug through the profile-setup chain on v1.4.232 to map how an account folder can come to exist with zero symlinks and no log line. The code has a designed-in window that matches your timeline exactly, plus a reason it would never self-heal. Three checks on your machine can confirm or kill it.
The window. Setup is the only thing that creates the 13 links, and it runs in two shapes: awaited in prepareLaunch when the marker (claude-profiles//profile.json — one level ABOVE home) is missing, and in the background from publish()/terminalEnv once the login-shell env has resolved. But terminalEnv deliberately returns pointer-only env BEFORE envResolved, and publish() writes the account home into the pointer file before any setup has run — its own comment says: "Why even a missing or covered folder: setup creates it without a login, so a sign-in, or Claude's own first run, signs in there." So the design explicitly lets Claude land in a folder Orca has not set up yet: a pane opened early after the update (env not yet resolved), with the pointer already naming your fifth account, launches claude → the shell function reads the pointer → CLAUDE_CONFIG_DIR= → Claude creates the folder itself on first run. That produces exactly your observation: home created ~28 min after the others (first use of that account, not the migration wave), zero symlinks (Orca's setup never ran), and zero Orca log lines (Orca never touched it).
Why it never heals. Background setup only fires for routedProfile() — the globally routed account. The marker-based awaited setup only runs in prepareLaunch's launch preparation. So if the fifth account never becomes the routed profile in a session where envResolved is true (e.g. you use it through panes that inherited the early pointer, while another account is the saved selection), setup never executes for it, the marker stays absent, and Claude keeps writing real directories (your impact #2 — sessions inside the account folder instead of ~/.claude/projects — is the fingerprint: on the four good accounts
projectsis a symlink; on the broken one it should be a REAL directory).Three checks that would confirm:
projectsa real directory with session data (not a symlink)? Same forsessions.If that holds, the fix shape is at the routing layer, not the link layer: the pointer file (or the claude shell function) should treat a marker-less home as "not ready" — either block the pointer write until setup completes, or have the shell function fall back to the user's own config dir when the pointed-at folder has no marker. Happy to build the failing test and PR once the checks confirm which side of the race your machine hit.
fix(claude): share folders Claude made in an account folder before it…
nwparker commentedon Oct 25, 2026
#33479 (merged) fixes one cause we could reproduce: if Claude runs in a brand-new account before Orca's background setup finishes, Claude creates its own
plugins/folder and setup used to leave it unlinked, so plugins showed as "not cached". New accounts now merge and link it on first setup. Accounts that already hit this don't heal automatically: deleteclaude-profiles/<id>/home/pluginsand start Claude again. We couldn't reproduce the state where no shared folders were linked at all on current main. If you still see that on the next build, could you share your Orca version and OS, and a listing of that account'shomefolder (names only,ls -la)?eatmoreduck commentedon Oct 27, 2026
The reporter has been quiet for 48h, so I kept digging on the window my analysis left open — the part #33479 doesn't cover (it fixes the healing side: first setup now adopts folders Claude made; it does not change when setup gets a chance to run). While scoping a fix I hit what looks like a real design tension that's worth a maintainer call before anyone builds the "treat a marker-less home as not ready" variant:
An unconditional marker gate in the
claudeshell function would break the deliberate flow it currently implements: the function creates a missing home on purpose (mkdir -p -m 700, header comment "Create account homes without a login silently") so that a newly added account's first run signs in inside that account's folder before setup has completed — and #33479's first-setup merge exists precisely to adopt what Claude writes there. Gating on the marker would send that first run to the user's own config dir instead, i.e. the login lands in the wrong place. So the naive routing-layer gate is not actually safe.The narrower window my analysis named — pointer already naming an account whose setup never fires because background setup only runs for the routed (saved-selection) profile, while the pane's pointer can name a different account — still seems open, and it doesn't need the shell function to change. Two candidates that leave the first-run design intact:
publish()fire the one-shot background setup for an account it is about to point at that has no marker — the same adoption fix(claude): share folders Claude made in an account folder before its first setup #33479 performs at first setup, just triggered at pointer-write time instead of waiting for a launch.Both stay inside the existing marker semantics ("missing marker = setup hasn't run") and neither touches the shell function bytes. Happy to build the failing test and PR for whichever direction you prefer — the repro harness in
claude-shell-function.test.tsalready runs real shells, so the no-setup-fires scenario can be expressed there or next topublish()'s tests. If the reporter's three checks ever come back, they'd confirm which account hit this window, but the window itself is code-visible either way.