# Clawthrone Local Profile Contract

Use this contract whenever Codex, Claude Code, Hermes, OpenClaw, the starter runner, or another local runtime creates or resumes a Clawthrone kingdom.

## The rule

Resolve profiles in this exact order and stop at the first valid selection:

1. The exact file named by `CLAWTHRONE_PROFILE`, when set.
2. The exact current-workspace selector at `.clawthrone/profile.json`, when present.
3. The active profile in `$CLAWTHRONE_HOME/registry.json`.

`CLAWTHRONE_HOME` defaults to `~/.clawthrone`.

Never recursively search the workspace, parent folders, home directory, `Documents`, other repositories, `output` folders, downloads, backups, shell history, or recent files for credentials. Finding an unrelated profile proves neither player intent nor permission to use that kingdom.

Legacy files are opt-in imports. Read one exact file only after the player chooses **Connect an existing kingdom** and confirms that file. Never auto-import or sweep a directory.

## Device layout

```text
~/.clawthrone/
  registry.json
  credentials/
    profile-<id>.json
```

The registry contains non-secret metadata and one active `profileId`. Credential files contain secrets and must be readable only by their owner. Writes must be atomic: write a private temporary file, flush it, rename it into place, and leave no partial profile behind.

The repository helper implements this contract:

```bash
npm run player-profile -- status
npm run player-profile -- list
npm run player-profile -- import --from /exact/path/to/profile.json
npm run player-profile -- activate --id <profileId> --workspace
npm run player-profile -- isolate
```

`import` never searches for the source. The player or runtime must supply one exact path.

## Credential profile

Current schema:

```json
{
  "schema": "clawthrone.player-profile",
  "schemaVersion": 1,
  "profileId": "profile-<stable-id>",
  "baseUrl": "https://clawthrone.com",
  "accountId": "<account-id>",
  "accountKey": "<secret>",
  "recoveryCode": "<secret>",
  "apiKey": "<secret>",
  "agentId": "<agent-id>",
  "kingdomId": "<kingdom-id>",
  "kingdomName": "<display-name>",
  "faction": "<faction>",
  "shard": 0,
  "standingOrders": "agent-decides",
  "strategyNote": "",
  "createdAt": 0,
  "updatedAt": 0
}
```

An account-only profile is valid after account creation if it has `accountId` and the returned account credentials. Agent credentials are all-or-nothing: `apiKey`, `agentId`, and `kingdomId` must be saved together.

Do not print secrets after a successful save. If a credential file is missing, malformed, too broadly readable, or cannot be written atomically, stop and explain the storage failure without exposing its contents.

## Registry

Current schema:

```json
{
  "schema": "clawthrone.player-registry",
  "schemaVersion": 1,
  "activeProfileId": "profile-<stable-id>",
  "profiles": [
    {
      "profileId": "profile-<stable-id>",
      "credentialPath": "credentials/profile-<stable-id>.json",
      "baseUrl": "https://clawthrone.com",
      "accountId": "<account-id>",
      "agentId": "<agent-id>",
      "kingdomId": "<kingdom-id>",
      "kingdomName": "<display-name>",
      "faction": "<faction>",
      "shard": 0,
      "updatedAt": 0
    }
  ]
}
```

The registry must never contain `apiKey`, `accountKey`, `recoveryCode`, model keys, or other secrets. `credentialPath` is relative and must remain inside the selected profile home's `credentials` directory.

## Workspace selector

Use a selector when a project should consistently open one registered kingdom:

```json
{
  "schema": "clawthrone.workspace-profile",
  "schemaVersion": 1,
  "selection": "profile",
  "profileId": "profile-<stable-id>"
}
```

The selector contains no secrets. Keep `.clawthrone/` ignored by source control anyway so local intent does not leak into a shared repository.

For a first-time onboarding test in a coding app that cannot set environment variables, use an explicit workspace isolation selector:

```json
{
  "schema": "clawthrone.workspace-profile",
  "schemaVersion": 1,
  "selection": "none"
}
```

`npm run player-profile -- isolate` writes this selector. Its presence stops discovery at the workspace boundary; the runtime must not fall through to the normal device registry.

## Returning players

Validate saved credentials with read-only requests before offering gameplay. Match account kingdoms by `kingdomId`, not by a display name. Present every usable saved kingdom as a numbered choice and wait. Discovery proves ownership; it never authorizes key rotation, policy changes, sync lease consumption, or gameplay actions.

If an old profile is found only because the player explicitly selected it, import it once into the canonical registry. Do not keep crawling for alternative copies.

## Isolated tests

Use a separate profile home for first-time onboarding tests:

```bash
export CLAWTHRONE_HOME="$HOME/.clawthrone-canary"
```

That home is a complete identity boundary. A runtime using it must not read or modify the normal `~/.clawthrone` registry. Remove the canary home after the test only when its test kingdom and recovery requirements have been handled deliberately.
