feat: add ocp keys, ocp lan, and ocp usage --by-key CLI commands

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-10 21:16:25 +10:00
co-authored by Claude Sonnet 4.6
parent ea57db6ceb
commit 4f4e1edf16
+147 -3
View File
@@ -29,11 +29,36 @@ Displays current session utilization, weekly limits, extra usage status,
and proxy request statistics. Data is fetched from the Anthropic API and proxy request statistics. Data is fetched from the Anthropic API
via a minimal probe call (cached for 5 minutes). via a minimal probe call (cached for 5 minutes).
Usage: ocp usage Usage: ocp usage [--by-key]
Options:
--by-key Show per-key usage statistics
EOF EOF
} }
cmd_usage() { cmd_usage() {
if [[ "${1:-}" == "--by-key" ]]; then
local data
data=$(curl -sf --max-time 15 "$PROXY/api/usage" 2>&1) || { echo "Error: proxy unreachable or usage API not available"; exit 1; }
echo "$data" | python3 -c "
import sys, json
d = json.loads(sys.stdin.read())
by_key = d.get('byKey', [])
if not by_key:
print('No usage data yet.')
else:
print('Usage by Key')
print('─────────────────────────────────────────────────────────────────')
hdr = f' {\"Key\":<20} {\"Reqs\":>5} {\"OK\":>4} {\"Err\":>4} {\"Avg Time\":>9} {\"Last Request\":<20}'
print(hdr)
print(' ' + '─' * (len(hdr) - 2))
for k in by_key:
avg_t = f'{k[\"avg_elapsed_ms\"]/1000:.1f}s' if k['avg_elapsed_ms'] else '-'
print(f' {k[\"key_name\"]:<20} {k[\"requests\"]:>5} {k[\"successes\"]:>4} {k[\"errors\"]:>4} {avg_t:>9} {k[\"last_request\"]:<20}')
"
return
fi
local data local data
data=$(curl -sf --max-time 15 "$PROXY/usage" 2>&1) || { echo "Error: proxy unreachable"; exit 1; } data=$(curl -sf --max-time 15 "$PROXY/usage" 2>&1) || { echo "Error: proxy unreachable"; exit 1; }
@@ -213,6 +238,121 @@ cmd_clear() {
echo "Cleared $count sessions." echo "Cleared $count sessions."
} }
# ── keys ────────────────────────────────────────────────────────────────
cmd_keys_help() {
cat <<'EOF'
ocp keys — Manage API keys (multi-key auth mode)
Usage:
ocp keys List all keys
ocp keys add <name> Create a new key
ocp keys revoke <name|id> Revoke a key
Examples:
ocp keys add wife-laptop
ocp keys add son-ipad
ocp keys revoke wife-laptop
EOF
}
cmd_keys() {
case "${1:-}" in
add)
if [[ -z "${2:-}" ]]; then echo "Usage: ocp keys add <name>"; return 1; fi
local result
result=$(curl -sf --max-time 5 -X POST "$PROXY/api/keys" \
-H "Content-Type: application/json" \
-d "{\"name\": \"$2\"}" 2>&1) || { echo "Error: proxy unreachable or unauthorized"; exit 1; }
echo "$result" | python3 -c "
import sys, json
d = json.loads(sys.stdin.read())
if 'key' in d:
print(f'✓ Key created for \"{d[\"name\"]}\"')
print(f'')
print(f' API Key: {d[\"key\"]}')
print(f'')
print(f' Copy this key now — you won\\'t see it again.')
print(f' Configure in IDE: OPENAI_API_KEY={d[\"key\"]}')
else:
print(f'✗ {d.get(\"error\", \"Unknown error\")}')
"
;;
revoke)
if [[ -z "${2:-}" ]]; then echo "Usage: ocp keys revoke <name|id>"; return 1; fi
curl -sf --max-time 5 -X DELETE "$PROXY/api/keys/$2" | python3 -c "
import sys, json
d = json.loads(sys.stdin.read())
if d.get('revoked'):
print(f'✓ Key \"{d[\"idOrName\"]}\" revoked.')
else:
print(f'✗ Key not found or already revoked.')
"
;;
--help|-h)
cmd_keys_help
;;
"")
curl -sf --max-time 5 "$PROXY/api/keys" | python3 -c "
import sys, json
d = json.loads(sys.stdin.read())
keys = d.get('keys', [])
if not keys:
print('No API keys configured.')
print('Create one: ocp keys add <name>')
else:
print('API Keys')
print('─────────────────────────────────────────────────')
for k in keys:
status = '✗ revoked' if k['revoked'] else '✓ active'
print(f' {k[\"name\"]:<20} {k[\"keyPreview\"]:<20} {status} {k[\"created_at\"]}')
" 2>/dev/null || { echo "Error: proxy unreachable or key management not available"; exit 1; }
;;
*)
echo "Unknown subcommand: $1"; cmd_keys_help; return 1 ;;
esac
}
# ── lan ─────────────────────────────────────────────────────────────────
cmd_lan_help() {
cat <<'EOF'
ocp lan — Quick LAN mode setup guide
Shows current network configuration and connection instructions
for other devices on the same network.
Usage: ocp lan
EOF
}
cmd_lan() {
local ip
ip=$(ipconfig getifaddr en0 2>/dev/null || hostname -I 2>/dev/null | awk '{print $1}')
local port=3456
echo "OCP LAN Setup"
echo "─────────────────────────────────────"
echo ""
echo " Your IP: $ip"
echo " Port: $port"
echo ""
echo " For IDE users, set:"
echo " OPENAI_BASE_URL=http://$ip:$port/v1"
echo " OPENAI_API_KEY=<your-key> (if auth enabled)"
echo ""
echo " Dashboard: http://$ip:$port/dashboard"
echo ""
if curl -sf --max-time 2 "http://$ip:$port/health" > /dev/null 2>&1; then
echo " Status: ✓ LAN-accessible"
else
echo " Status: ✗ Not LAN-accessible (bound to localhost only)"
echo ""
echo " To enable LAN mode, set env var and restart:"
echo " CLAUDE_BIND=0.0.0.0"
echo " ocp restart"
fi
}
# ── restart ────────────────────────────────────────────────────────────── # ── restart ──────────────────────────────────────────────────────────────
cmd_restart_help() { cmd_restart_help() {
cat <<'EOF' cat <<'EOF'
@@ -442,7 +582,7 @@ ocp — OpenClaw Proxy CLI
Usage: ocp <command> [args] Usage: ocp <command> [args]
Commands: Commands:
usage Plan usage limits usage Plan usage limits (--by-key for per-key stats)
status Quick overview (usage + health) status Quick overview (usage + health)
health Proxy diagnostics health Proxy diagnostics
settings View or update tunable settings settings View or update tunable settings
@@ -450,6 +590,8 @@ Commands:
models Available models models Available models
sessions Active sessions sessions Active sessions
clear Clear all sessions clear Clear all sessions
keys Manage API keys (add/list/revoke)
lan LAN mode setup guide
restart Restart proxy restart Restart proxy
restart gateway Restart gateway restart gateway Restart gateway
update Update OCP to latest version update Update OCP to latest version
@@ -484,7 +626,7 @@ for arg in "$@"; do
done done
case "$subcmd" in case "$subcmd" in
usage) cmd_usage ;; usage) cmd_usage "${1:-}" ;;
status) cmd_status ;; status) cmd_status ;;
health) cmd_health ;; health) cmd_health ;;
settings) cmd_settings "${1:-}" "${2:-}" ;; settings) cmd_settings "${1:-}" "${2:-}" ;;
@@ -492,6 +634,8 @@ case "$subcmd" in
models) cmd_models ;; models) cmd_models ;;
sessions) cmd_sessions ;; sessions) cmd_sessions ;;
clear) cmd_clear ;; clear) cmd_clear ;;
keys) cmd_keys "${1:-}" "${2:-}" ;;
lan) cmd_lan ;;
restart) cmd_restart "${1:-}" ;; restart) cmd_restart "${1:-}" ;;
update) cmd_update "${1:-}" ;; update) cmd_update "${1:-}" ;;
*) echo "Unknown command: $subcmd"; echo ""; cmd_help; exit 1 ;; *) echo "Unknown command: $subcmd"; echo ""; cmd_help; exit 1 ;;