Link the Claude config into native session homes and pre-accept workspace trust #956

Closed
opened 2026-08-06 17:24:26 +00:00 by coilyco-ops · 1 comment
Member

Observed failure

A native Claude session starts on an empty per-user config. acompose sets
CLAUDE_CONFIG_DIR to the session home's .claude, and
stageNativeRoleConfigDirectory symlinks every entry of the host .claude
except skills. The host config file is ~/.claude.json at the home root, one
level above that directory, so nothing links it and Claude Code creates a fresh
file in the session.

Confirmed on a live session: the host config carried 12 MCP servers and 171
project entries, while the session config had mcpServers: {} and no project
state. The harness reports no error, so the loss is silent.

Consequences per session:

  • The folder-trust dialog appears every launch.
  • Every configured MCP server is absent. Only account-hosted connectors remain,
    which makes the session look like MCP is working.
  • Onboarding, allowed tools, and recorded permission decisions reset.

projectNativeMCP renders its Claude payload to filepath.Join(home, ".claude.json"), so the MCP projection writes the host file while the running
session reads a different one. Projection and consumption disagree.

Codex is unaffected because CODEX_HOME points at .codex and config.toml
genuinely lives inside it. The defect is the filesystem shape, not the launcher.

Folder trust is a second, independent defect: it is keyed by absolute project
path, and each session mints a fresh workspace path, so linking the config
alone still re-prompts every launch.

Acceptance

  • One resolver owns the Claude config location for the CLI, and both the MCP
    projection and session staging use it.
  • A staged session home reaches the host config through its CLAUDE_CONFIG_DIR.
  • A standalone home keeps its sealed boundary and does not gain a view of the
    host config.
  • The launcher pre-accepts the workspace paths it creates, in both the raw and
    symlink-resolved spelling, and a seeding failure never blocks a launch.
  • Writers resolve the link before an atomic rename, so a session keeps a
    symlink rather than a divergent copy.
  • Repository validation passes.
## Observed failure A native Claude session starts on an empty per-user config. `acompose` sets `CLAUDE_CONFIG_DIR` to the session home's `.claude`, and `stageNativeRoleConfigDirectory` symlinks every entry of the host `.claude` except `skills`. The host config file is `~/.claude.json` at the home root, one level above that directory, so nothing links it and Claude Code creates a fresh file in the session. Confirmed on a live session: the host config carried 12 MCP servers and 171 project entries, while the session config had `mcpServers: {}` and no project state. The harness reports no error, so the loss is silent. Consequences per session: * The folder-trust dialog appears every launch. * Every configured MCP server is absent. Only account-hosted connectors remain, which makes the session look like MCP is working. * Onboarding, allowed tools, and recorded permission decisions reset. `projectNativeMCP` renders its Claude payload to `filepath.Join(home, ".claude.json")`, so the MCP projection writes the host file while the running session reads a different one. Projection and consumption disagree. Codex is unaffected because `CODEX_HOME` points at `.codex` and `config.toml` genuinely lives inside it. The defect is the filesystem shape, not the launcher. Folder trust is a second, independent defect: it is keyed by absolute project path, and each session mints a fresh workspace path, so linking the config alone still re-prompts every launch. ## Acceptance * One resolver owns the Claude config location for the CLI, and both the MCP projection and session staging use it. * A staged session home reaches the host config through its `CLAUDE_CONFIG_DIR`. * A standalone home keeps its sealed boundary and does not gain a view of the host config. * The launcher pre-accepts the workspace paths it creates, in both the raw and symlink-resolved spelling, and a seeding failure never blocks a launch. * Writers resolve the link before an atomic rename, so a session keeps a symlink rather than a divergent copy. * Repository validation passes.
Author
Member

Landed on main as 974c9471.

aos-cli/native_claude_config.go owns the config-location resolver,
stageNativeRoleHome links the host file into the session CLAUDE_CONFIG_DIR,
projectNativeMCP resolves through the same helper, and the launcher seeds
folder trust for the workspace paths it creates.

Validation: ward exec aos-fmt, ward exec aos-lint, ward exec aos-test
(537 tests, 219s), and pre-commit run --all-files, all passing.

Walkthrough: docs/native-claude-config.md.

Not covered here: the session projects root is still per-launch, so trust
depends on the seeding step rather than a stable path. A stable-slot workspace
root remains an open design option.

WARD-OUTCOME: done

Landed on `main` as `974c9471`. `aos-cli/native_claude_config.go` owns the config-location resolver, `stageNativeRoleHome` links the host file into the session `CLAUDE_CONFIG_DIR`, `projectNativeMCP` resolves through the same helper, and the launcher seeds folder trust for the workspace paths it creates. Validation: `ward exec aos-fmt`, `ward exec aos-lint`, `ward exec aos-test` (537 tests, 219s), and `pre-commit run --all-files`, all passing. Walkthrough: `docs/native-claude-config.md`. Not covered here: the session projects root is still per-launch, so trust depends on the seeding step rather than a stable path. A stable-slot workspace root remains an open design option. WARD-OUTCOME: done
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agentic-os#956
No description provided.