Mount .claude.json so container logins persist; allow isolating state - #4
Open
systemjack wants to merge 1 commit into
Open
Mount .claude.json so container logins persist; allow isolating state#4systemjack wants to merge 1 commit into
systemjack wants to merge 1 commit into
Conversation
Claude Code keeps state in two places and both are required for a session to
survive a restart:
~/.claude/ credentials, history, settings, plugin cache and registry
~/.claude.json FILE at HOME root: account linkage, onboarding, project state
The launchers mounted only the directory. So .credentials.json persisted fine,
but .claude.json was absent on every start, Claude Code saw no linked account,
and prompted for login each launch -- with a perfectly good credential sitting in
the mounted directory unused.
Mounting the pair fixes that. Both mounts now come from one shared function in
localdev-mounts.sh rather than a copy in each launcher, so the three cannot
drift apart.
Also adds LOCALDEV_CLAUDE_STATE to choose which host directory supplies that
pair, defaulting to $HOME (existing shared behaviour). Sharing has a real cost
that mounting .claude.json increases: host and container run different Claude
Code builds against one mutable registry and reset each other's state. A
container session was observed emptying the host's installed_plugins.json,
disabling the org's managed plugins on the host. Pointing
LOCALDEV_CLAUDE_STATE at a container-only directory gives the container its own
credential and plugin state and removes that failure mode, at the cost of one
extra login.
A nonexistent .claude.json is seeded with '{}' before mounting: podman creates a
directory for a missing bind-mount source, which would hand Claude Code a
directory where it expects a JSON file.
Verified across all three launchers: shared mode mounts the dir and the json from
$HOME; isolated mode mounts both from LOCALDEV_CLAUDE_STATE and nothing from
$HOME, seeding the directory and file on first use.
Documents both in README: that Claude Code state spans a directory and a file,
and the LOCALDEV_CLAUDE_STATE choice with the tradeoff behind it. Without that,
the variable is discoverable only by reading the library source.
Author
|
This PR maybe not ready for prime time. The refactor for common function is probably okay but I have mixed feelings about the LOCALDEV_CLAUDE_STATE bit. Not sure it actually works like I want. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Claude Code keeps state in two places and both are required for a session to
survive a restart:
~/.claude/ credentials, history, settings, plugin cache and registry
~/.claude.json FILE at HOME root: account linkage, onboarding, project state
The launchers mounted only the directory. So .credentials.json persisted fine,
but .claude.json was absent on every start, Claude Code saw no linked account,
and prompted for login each launch -- with a perfectly good credential sitting in
the mounted directory unused.
Mounting the pair fixes that. Both mounts now come from one shared function in
localdev-mounts.sh rather than a copy in each launcher, so the three cannot
drift apart.
Also adds LOCALDEV_CLAUDE_STATE to choose which host directory supplies that
pair, defaulting to $HOME (existing shared behaviour). Sharing has a real cost
that mounting .claude.json increases: host and container run different Claude
Code builds against one mutable registry and reset each other's state. A
container session was observed emptying the host's installed_plugins.json,
disabling the org's managed plugins on the host. Pointing
LOCALDEV_CLAUDE_STATE at a container-only directory gives the container its own
credential and plugin state and removes that failure mode, at the cost of one
extra login.
A nonexistent .claude.json is seeded with '{}' before mounting: podman creates a
directory for a missing bind-mount source, which would hand Claude Code a
directory where it expects a JSON file.
Verified across all three launchers: shared mode mounts the dir and the json from
$HOME; isolated mode mounts both from LOCALDEV_CLAUDE_STATE and nothing from
$HOME, seeding the directory and file on first use.
Documents both in README: that Claude Code state spans a directory and a file,
and the LOCALDEV_CLAUDE_STATE choice with the tradeoff behind it. Without that,
the variable is discoverable only by reading the library source.