Skip to content

Keychain-credentials auth: boot-time ~/.claude.json marker resets hasCompletedOnboarding, forcing re-login every boot #8

Description

@gitthass

When using the keychain-credentials path (no long-lived OAuth token configured), the seeded credentials work — but the agent is thrown back into Claude Code's onboarding/login flow on every boot, even though ~/.claude/.credentials.json is present and valid.

Setup

  • clawk built from source at current main (7c1c1d1, the env: aliases, defaults, and literals; fix profile.d perms (#4) #5 merge), macOS Apple silicon, vz provider, cwd sandbox
  • No ~/.clawk/claude-oauth-token (removed deliberately, to use the credentials path)
  • Host Mac logged into Claude Code interactively; SeedClaudeStateDir correctly seeds Claude Code-credentials from the keychain into the sandbox state dir

What happens

  1. First boot: agent authenticated via the seeded .credentials.json. Works.
  2. clawk down && clawk up
  3. Attach → Claude Code re-runs first-run onboarding and asks to log in again — despite ~/.claude/.credentials.json persisting fine (it lives in the state-dir mount).

Cause (from source)

  • ClaudeJSONMarkerFile (internal/sandbox/oauth_token.go) sets hasCompletedOnboarding: true only when hasToken — the comment says "only when hasToken — the keychain credentials path doesn't need it".
  • The marker is pushed via pushHostFiles on every up (bringUpVZ), overwriting whatever ~/.claude.json Claude wrote during the previous session (which included its own hasCompletedOnboarding and account state).
  • Current Claude Code does need the flag: with valid .credentials.json but a ~/.claude.json lacking hasCompletedOnboarding, it re-enters the onboarding/login flow. So on the credentials path, every boot logs the agent out.

Verified workaround

Confirms the diagnosis: after boot, re-set the flag and Claude comes up logged in with the seeded credentials, no prompt:

node -e 'const fs=require("fs"),p="/home/agent/.claude.json";const d=JSON.parse(fs.readFileSync(p));d.hasCompletedOnboarding=true;fs.writeFileSync(p,JSON.stringify(d,null,2))'

(we run this as an on up hook for now)

Suggested fix

Set hasCompletedOnboarding: true in the marker whenever the state dir has a .credentials.json (i.e. hasToken || credentialsSeeded), not only for the token path.

Why the credentials path matters

This currently seems to be the only way to use a subscription account inside clawk.

Somewhat related: a snapshot-restored boot re-pushes the marker but (correctly) skips on up hooks, so even the hook workaround misses that path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions