Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .trinity/seals/queen_QueenKeyVault.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"built_by": "t27c-bootstrap@0.5.2+9448ab4be",
"closure": [
{
"spec": "specs/queen/key_failover.t27",
"spec_hash": "sha256:822367357fc6b487c1c7fb7ac8369165e6a7e6636fd9b0dcafec29e9a6274301"
},
{
"spec": "specs/queen/reviewer_sizing.t27",
"spec_hash": "sha256:7a37c374021c2143bcccfa22c9e6e6d69bb25d21a06ef33442a26902a51d0a8e"
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:e2ecd4302208c532e417ad207206db2140aeffbbad282add8f5249bc526c478b",
"gen_hash_rust": "sha256:94f44d51c436fbde5bd5b1385da8b16faaaeb9ddc0e650f40cc81b4478c554eb",
"gen_hash_verilog": "sha256:d10fc885c476a90c7c44ca887b9567e5f60a70a25fdf2d240205cc93aa9e10a4",
"gen_hash_zig": "sha256:28242e4d9504706f2f1cec32384a00051f056d8da28c81f1cc34e7329fa6e3fe",
"module": "QueenKeyVault",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-18T17:29:18Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:caa5c0913648ec6eb545c0544fe0d51e383c42f5b4617ae25db6f542f2fa4097",
"spec_path": "specs/queen/key_vault.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 8,
"total": 8,
"vacuous": 0
},
"toolchain": {
"test_runner": "sha256:8512b80da533b79289110fca4a65f3336abd7a059ca4b72ea595d5e33ff8ad10",
"zig": "0.16.0"
}
}
93 changes: 7 additions & 86 deletions contrib/portable-claude-setup/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ Dotfiles-style bundle for [Claude Code](https://www.anthropic.com/claude-code):
| `env.example` | Variables to copy into `~/.claude/.env` |
| `scripts/sync-settings-from-env.sh` | Merges `.env` into `settings.json` (`env.*` and optional MCP commands) |
| `scripts/apply-anthropic-token-from-env.sh` | Legacy name; calls `sync-settings-from-env.sh` |
| `scripts/rotate-keys.sh` | Rotate numbered API keys (round-robin / random / health-check) |
| `scripts/check-key-health.sh` | Test all configured keys and report status |

## Clone from GitHub

Expand Down Expand Up @@ -46,94 +44,17 @@ cd portable-claude-setup

Set `ZAI_USE=2` and `ZAI_KEY_2=...`; otherwise the first non-empty `ZAI_KEY_1`, `ZAI_KEY_2`, … (numeric order) is used.

## Key Rotation
## Key rotation

When you have multiple API keys for the same provider (e.g. several Railway accounts), the rotation scripts let you cycle through them automatically.

### Setup

Add numbered keys to `~/.claude/.env`:

```bash
# Railway accounts
RAILWAY_TOKEN_1=railway-token-aaa
RAILWAY_TOKEN_2=railway-token-bbb
RAILWAY_TOKEN_3=railway-token-ccc

# GitHub tokens
GH_TOKEN_1=ghp_aaa
GH_TOKEN_2=ghp_bbb

# OpenAI keys
OPENAI_KEY_1=sk-aaa
OPENAI_KEY_2=sk-bbb

# Z.AI / Anthropic (existing ZAI_KEY_N vars are already supported)
ZAI_KEY_1=sk-ant-aaa
ZAI_KEY_2=sk-ant-bbb
```

### Rotating keys

```bash
# Rotate all families (round-robin, default)
bash scripts/rotate-keys.sh

# Rotate a specific family
bash scripts/rotate-keys.sh --family railway

# Pick a random key
bash scripts/rotate-keys.sh --random

# Test each key, use the first healthy one
bash scripts/rotate-keys.sh --health-check

# View current state
bash scripts/rotate-keys.sh --status
```

Rotation state is stored in `~/.claude/.rotation-state.json`. After each rotation, `sync-settings-from-env.sh` runs automatically to update `settings.json`.

### Health check

Test all configured keys without rotating:

```bash
bash scripts/check-key-health.sh
```

### Cron integration

Auto-rotate every 30 minutes with a health check:

```cron
*/30 * * * * bash ~/portable-claude-setup/scripts/rotate-keys.sh --health-check
```

Or check health and alert (no rotation):

```cron
0 */6 * * * bash ~/portable-claude-setup/scripts/check-key-health.sh || echo "Key failure" | mail -s "API key down" you@example.com
```
There is none here, on purpose. Owner, 2026-10-18: every API key lives in one place, the Queen's
store, and is shared out to everyone who uses it (`specs/queen/key_vault.t27` in gHashTag/t27,
#10564). A numbered pool of private keys rotated on one machine is a second home for keys that
nobody else can see or share, so the rotation scripts that lived here were deleted. A consumer
that needs a model leases from the Queen (for the reviewer bees: `BEE_QUEEN_LEASE_URL` and
`BEE_QUEEN_LEASE_TOKEN`); keys you hold go into her store through the contributor-key flow.

## Security

- **Do not push** your entire `~/.claude` directory: it may include `history.jsonl`, plugin caches, and tracked `settings.json` with secrets.
- This repo should contain **only** templates and scripts—no `.env` or real tokens.

## OpenCode key rotation

Analogous to the Claude Code rotation above, `rotate-opencode-keys.sh` manages ZAI keys in `~/.local/share/opencode/auth.json`:

```bash
# Rotate ZAI keys (reads ZAI_KEY_1..N from ~/.claude/.env)
bash scripts/rotate-opencode-keys.sh

# View current state
bash scripts/rotate-opencode-keys.sh --status

# Random key selection
bash scripts/rotate-opencode-keys.sh --random
```

After rotation, `anthropic` and `zai-coding-plan` providers in `auth.json` point to the active key. All keys are also stored as `zai-1`..`zai-N` for manual provider selection.
162 changes: 0 additions & 162 deletions contrib/portable-claude-setup/scripts/check-key-health.sh

This file was deleted.

Loading
Loading