Skip to content

Commit 0c5e3f5

Browse files
committed
feat: add fleet-cc-switch for multi-account Claude Code auth
1 parent 747cff7 commit 0c5e3f5

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

agents/fleet-cc-switch.sh

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
OP_VAULT="Personal Agents"
5+
OP_ITEM="claude-code-oauth"
6+
ACCOUNTS=("" "zctaylor.work@gmail.com" "zachncst@gmail.com" "ztaylor@stigen.ai")
7+
SSH_HOST="gti"
8+
AGENT_NAMESPACES="agent-coder agent-sre agent-pm agent-sage agent-orchestrator agent-personal"
9+
10+
usage() {
11+
cat <<EOF
12+
Usage: fleet-cc-switch <1|2|3> [--restart]
13+
fleet-cc-switch --status
14+
15+
Switch which Claude Code Max account token is active across the fleet.
16+
17+
Accounts:
18+
1 ${ACCOUNTS[1]}
19+
2 ${ACCOUNTS[2]}
20+
3 ${ACCOUNTS[3]}
21+
22+
Options:
23+
--status, -s Show current active account and stored tokens
24+
--restart After switching, restart 1Password operator + agent pods
25+
26+
Examples:
27+
fleet-cc-switch --status # Check current state
28+
fleet-cc-switch 2 # Switch to account 2 (1Password only)
29+
fleet-cc-switch 2 --restart # Switch + sync to K8s + restart pods
30+
EOF
31+
exit 1
32+
}
33+
34+
cmd_status() {
35+
local active
36+
active=$(op item get "$OP_ITEM" --vault "$OP_VAULT" --fields "active_account" --reveal 2>/dev/null || echo "?")
37+
echo "Active account: $active (${ACCOUNTS[$active]:-unknown})"
38+
echo ""
39+
for i in 1 2 3; do
40+
local has="no"
41+
op item get "$OP_ITEM" --vault "$OP_VAULT" --fields "account_${i}_token" --reveal >/dev/null 2>&1 && has="yes"
42+
echo " Account $i (${ACCOUNTS[$i]}): token stored=$has"
43+
done
44+
}
45+
46+
cmd_switch() {
47+
local target="$1"
48+
local restart="${2:-}"
49+
[[ "$target" =~ ^[123]$ ]] || usage
50+
51+
echo "Switching fleet to account $target (${ACCOUNTS[$target]})..."
52+
53+
# Read stored token for target account
54+
local token
55+
token=$(op item get "$OP_ITEM" --vault "$OP_VAULT" --fields "account_${target}_token" --reveal)
56+
if [[ -z "$token" ]]; then
57+
echo "ERROR: No token stored for account $target" >&2
58+
exit 1
59+
fi
60+
61+
# Update active token + account marker
62+
op item edit "$OP_ITEM" --vault "$OP_VAULT" \
63+
"CLAUDE_CODE_OAUTH_TOKEN[concealed]=$token" \
64+
"active_account=$target" >/dev/null
65+
66+
echo "Updated 1Password item. Active account: $target (${ACCOUNTS[$target]})"
67+
68+
if [[ "$restart" == "--restart" ]]; then
69+
echo "Restarting 1Password operator to force sync..."
70+
ssh "$SSH_HOST" sudo k0s kubectl rollout restart deployment/onepassword-connect-operator -n onepassword
71+
sleep 10
72+
73+
echo "Rolling restart of agent pods..."
74+
for ns in $AGENT_NAMESPACES; do
75+
echo " Deleting ${ns}-0..."
76+
ssh "$SSH_HOST" sudo k0s kubectl delete pod "${ns}-0" -n "$ns" --ignore-not-found 2>/dev/null || true
77+
done
78+
echo "Done. Pods will restart with new token."
79+
else
80+
echo ""
81+
echo "Run with --restart to sync to K8s and restart agent pods."
82+
fi
83+
}
84+
85+
# Parse args
86+
case "${1:-}" in
87+
--status|-s) cmd_status ;;
88+
--help|-h) usage ;;
89+
[123]) cmd_switch "$1" "${2:-}" ;;
90+
*) usage ;;
91+
esac

0 commit comments

Comments
 (0)