From 07463c9c3724a3e82ba2ed1abfc0eddec24588fe Mon Sep 17 00:00:00 2001 From: Scott Karp Date: Thu, 15 Oct 2026 23:55:48 +0000 Subject: [PATCH] =?UTF-8?q?kohen:=20claude-key=20=E2=80=94=20Claude=20Code?= =?UTF-8?q?=20on=20the=20API=20key=20when=20the=20login=20is=20what=20fail?= =?UTF-8?q?ed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2026-10-15 21:08Z: the daemon's proactive OAuth refresh failed (no incident at Anthropic; most likely a cross-process race on the single-use refresh token), the credential was dropped, and every session on the VM showed "Login expired · Please run /login" until a browser login took at 23:50Z — two "Login interrupted" first. The gate was off; the fallback of 4acd56c4 could not help, because it is the same OAuth credential. scripts/claude-key starts Claude Code on the Anthropic API key from ~/.config/shorashim/upstream_keys (read at launch, never written), direct to Anthropic whatever settings.json says. Proven: `claude-key auth status` → authMethod api_key, apiKeySource ANTHROPIC_API_KEY; a -p run from a directory with a dead gate armed in project settings answered. KOHEN.md: the login recovery (claude-key, `claude auth login` from the shell, `auth status --text`). Co-Authored-By: Claude Fable 5.1 --- KOHEN.md | 30 ++++++++++++++++++++++++++---- scripts/claude-key | 16 ++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) create mode 100755 scripts/claude-key diff --git a/KOHEN.md b/KOHEN.md index 1e833320..ae40d91a 100644 --- a/KOHEN.md +++ b/KOHEN.md @@ -633,6 +633,10 @@ while the gate is armed there. Three tools, all in `scripts/` (install to claude-direct # start Claude Code straight to Anthropic, whatever # settings.json says (a --settings JSON on the command # line outranks every settings file); OAuth as usual +claude-key # the same, on the Anthropic API KEY from + # ~/.config/shorashim/upstream_keys instead of the + # subscription's OAuth token: no browser, no /login. + # Billed to the API console account, not the Max plan. claude-bikoret # start behind the gate; probes the gate first and, if # it does not answer, says so and starts claude-direct. # BIKORET_STRICT=1 claude-bikoret refuses instead. @@ -643,10 +647,28 @@ bikoret-settings on|off|status # it, not the builder; `off` is the recovery. ``` -Order of recovery: `claude-direct` (always works), then `bikoret-settings -off` if background sessions must also recover, then fix the pod -(`curl -s https://bikoret.ch/kodesh/health` names the failed check), then -`bikoret-settings on` and `claude-bikoret` again. +Order of recovery: `claude-direct` (always works while the OAuth token +is good), then `bikoret-settings off` if background sessions must also +recover, then fix the pod (`curl -s https://bikoret.ch/kodesh/health` +names the failed check), then `bikoret-settings on` and `claude-bikoret` +again. + +**When it is the login, not the gate.** Every session on the VM shares +one OAuth credential (`~/.claude/.credentials.json`); the access token +lives eight hours and the daemon refreshes it ahead of time. On +2026-10-15 21:08Z that refresh failed with no incident at Anthropic +(most likely two processes racing on the single-use refresh token), the +credential was dropped, and every session said "Login expired · Please +run /login" for 2 h 43 min. The browser flow from a remote shell is +fragile ("Login interrupted" twice before it took). Recovery: + +```bash +claude-key # work NOW on the API key; nothing to log in to +claude auth login # from the shell, not inside a session: prints the + # URL, paste the code it gives back; `--console` + # signs in to the API account instead of the plan +claude auth status --text # says which credential a launch would use +``` ### The second scroll — *Mishneh haTorah* diff --git a/scripts/claude-key b/scripts/claude-key new file mode 100755 index 00000000..d8cbf4d7 --- /dev/null +++ b/scripts/claude-key @@ -0,0 +1,16 @@ +#!/bin/bash +# Start Claude Code on the Anthropic API KEY instead of the subscription's +# OAuth token — the second leg of the fallback (KOHEN "Claude Code behind +# the gate — fallback"). For when /login fails or the OAuth refresh died +# (2026-10-15 21:08Z: the daemon's proactive refresh failed, every session +# on the VM showed "Login expired", and the browser flow took three tries +# from a remote shell). +# +# Billing: the API console account (pay per token), not the Max plan. +# The key is read from the upstream keys file at launch and never written +# anywhere. Direct to Anthropic, whatever settings.json says. +KEY=$(awk '$1=="anthropic"{print $2}' "$HOME/.config/shorashim/upstream_keys") +[ -n "$KEY" ] || { echo "no 'anthropic ' line in ~/.config/shorashim/upstream_keys" >&2; exit 1; } +export ANTHROPIC_API_KEY="$KEY" +unset ANTHROPIC_BASE_URL ANTHROPIC_CUSTOM_HEADERS +exec claude --settings '{"env":{"ANTHROPIC_BASE_URL":"https://api.anthropic.com","ANTHROPIC_CUSTOM_HEADERS":""}}' "$@"