Add LLM install guide for ClaudeHack setup
This commit is contained in:
577
LLM-INSTALL-CLAUDEHACK.md
Normal file
577
LLM-INSTALL-CLAUDEHACK.md
Normal file
@@ -0,0 +1,577 @@
|
||||
# LLM-INSTALL-CLAUDEHACK.md
|
||||
|
||||
Use this guide when an AI agent (OpenClaw, Claude Code, Codex, etc.) is asked to install the OAuth token sync system from this repo onto a fresh or existing OpenClaw host, and to expose a separate optional `claudehack` model provider.
|
||||
|
||||
## Goal
|
||||
|
||||
Install the OAuth token sync system from:
|
||||
|
||||
`https://git.eeqj.de/ROOH/openclaw_oauth_sync`
|
||||
|
||||
onto the target OpenClaw machine, without using the repo's interactive installer, and with these additional requirements:
|
||||
|
||||
- install the token sync manually by reading this repo's `setup.sh`, `scripts/`, `templates/`, and `docs/`
|
||||
- **skip webhook security entirely** (Step 11 in `setup.sh`)
|
||||
- add a **new optional provider** named `claudehack`
|
||||
- do **not** replace or modify existing providers beyond what is required to add `claudehack`
|
||||
- do **not** set `claudehack` as the system primary or fallback default
|
||||
- keep all existing OpenClaw behavior intact unless explicitly required below
|
||||
|
||||
---
|
||||
|
||||
## Hard Rules
|
||||
|
||||
1. **Do NOT run `setup.sh` interactively.**
|
||||
- Read it to understand the system.
|
||||
- Perform the installation manually.
|
||||
|
||||
2. **Do NOT modify webhook security.**
|
||||
- Skip webhook security completely.
|
||||
- Skip Step 11 in `setup.sh`.
|
||||
|
||||
3. **Do NOT remove or overwrite existing providers, auth profiles, defaults, or models unless explicitly required below.**
|
||||
- This install is additive.
|
||||
|
||||
4. **Do NOT make `claudehack` the default model or fallback model.**
|
||||
- It must remain an optional selectable provider.
|
||||
|
||||
5. **Do NOT guess paths.**
|
||||
- Detect actual paths on the machine first.
|
||||
|
||||
6. **Do NOT assume all per-agent files already exist.**
|
||||
- Create missing `models.json` or `auth-profiles.json` files where required.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
apt-get update
|
||||
apt-get install -y inotify-tools python3 curl
|
||||
```
|
||||
|
||||
Verify Docker and Docker Compose v2 are available:
|
||||
|
||||
```bash
|
||||
docker compose version
|
||||
```
|
||||
|
||||
If Node.js is not installed on the host, install it:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
|
||||
apt-get install -y nodejs
|
||||
```
|
||||
|
||||
Then install Claude CLI on the host:
|
||||
|
||||
```bash
|
||||
npm install -g @anthropic-ai/claude-code
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 1 — Identify OpenClaw Paths
|
||||
|
||||
Find the actual OpenClaw paths on the machine.
|
||||
|
||||
Defaults are usually:
|
||||
|
||||
- `OPENCLAW_CONFIG_DIR=/root/.openclaw`
|
||||
- `COMPOSE_DIR=/root/openclaw`
|
||||
|
||||
These should contain:
|
||||
|
||||
- `/root/.openclaw/openclaw.json`
|
||||
- `/root/openclaw/docker-compose.yml`
|
||||
- `/root/openclaw/.env`
|
||||
|
||||
Find the gateway container name:
|
||||
|
||||
```bash
|
||||
docker ps --filter name=openclaw --format '{{.Names}}' | grep gateway
|
||||
```
|
||||
|
||||
Set and verify:
|
||||
|
||||
- `OPENCLAW_CONFIG_DIR`
|
||||
- `COMPOSE_DIR`
|
||||
- `GATEWAY_CONTAINER`
|
||||
|
||||
Do not continue until these are confirmed.
|
||||
|
||||
---
|
||||
|
||||
## Step 2 — Install and Authenticate Claude CLI
|
||||
|
||||
Claude CLI must be authenticated on the **host**, because this install relies on the Claude CLI OAuth credentials file and its token refresh behavior.
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
claude
|
||||
```
|
||||
|
||||
This opens the OAuth login flow. Complete the authentication in the browser.
|
||||
|
||||
Verify CLI access works:
|
||||
|
||||
```bash
|
||||
claude -p "say hello" --no-session-persistence
|
||||
```
|
||||
|
||||
Locate the credentials file:
|
||||
|
||||
```bash
|
||||
ls -la ~/.claude/.credentials.json
|
||||
```
|
||||
|
||||
On a standard root-based install, this file is usually:
|
||||
|
||||
```bash
|
||||
/root/.claude/.credentials.json
|
||||
```
|
||||
|
||||
Set:
|
||||
|
||||
- `CLAUDE_CREDS_FILE=/root/.claude/.credentials.json`
|
||||
or the actual discovered path
|
||||
|
||||
Do not continue unless the file exists and contains valid OAuth credentials.
|
||||
|
||||
---
|
||||
|
||||
## Step 3 — Install the Sync Script
|
||||
|
||||
Use the repo's `scripts/sync-oauth-token.sh` as the base.
|
||||
|
||||
Substitute these placeholders:
|
||||
|
||||
- `@@CLAUDE_CREDS_FILE@@` → credentials file path from Step 2
|
||||
- `@@OPENCLAW_OAUTH_FILE@@` → `/root/.openclaw/credentials/oauth.json`
|
||||
- `@@OPENCLAW_ENV_FILE@@` → `/root/openclaw/.env`
|
||||
- `@@COMPOSE_DIR@@` → `/root/openclaw`
|
||||
|
||||
Install the rendered script to:
|
||||
|
||||
```bash
|
||||
/root/sync-oauth-token.sh
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
```bash
|
||||
chmod +x /root/sync-oauth-token.sh
|
||||
```
|
||||
|
||||
### Required custom addition
|
||||
|
||||
After the `.env` update section in the sync script, and **before** the gateway recreate section, add this logic:
|
||||
|
||||
```bash
|
||||
FRESH_TOKEN=$(python3 -c "import json; d=json.load(open('$CLAUDE_CREDS_FILE')); print(d['claudeAiOauth']['accessToken'])")
|
||||
if [ -n "$FRESH_TOKEN" ]; then
|
||||
python3 /root/update-claudehack-profiles.py "$FRESH_TOKEN" 2>&1 | sed "s/^/$LOG_PREFIX /"
|
||||
fi
|
||||
```
|
||||
|
||||
### Create the helper profile updater
|
||||
|
||||
Create:
|
||||
|
||||
```bash
|
||||
/root/update-claudehack-profiles.py
|
||||
```
|
||||
|
||||
Make it executable:
|
||||
|
||||
```bash
|
||||
chmod +x /root/update-claudehack-profiles.py
|
||||
```
|
||||
|
||||
This script must:
|
||||
|
||||
- take the access token as its first argument
|
||||
- iterate over every:
|
||||
|
||||
```bash
|
||||
/root/.openclaw/agents/*/agent/auth-profiles.json
|
||||
```
|
||||
|
||||
- create missing files if needed
|
||||
- update the `"access"` field inside the `"claudehack:default"` profile
|
||||
- preserve other profile data
|
||||
- use the auth profile structure described in `setup.sh` Step 6
|
||||
|
||||
---
|
||||
|
||||
## Step 4 — Install the Trigger Script
|
||||
|
||||
Use the repo's `scripts/trigger-claude-refresh.sh` as the base.
|
||||
|
||||
Substitute:
|
||||
|
||||
- `@@CREDS_FILE@@` → the credentials file path from Step 2
|
||||
- `@@REAUTH_FLAG@@` → `/root/openclaw/REAUTH_NEEDED`
|
||||
- `@@CLI_MODE@@` → `host`
|
||||
- `@@CLI_CONTAINER@@` → empty / unused
|
||||
- `@@CLI_BASE_URL_OVERRIDE@@` → `false`
|
||||
|
||||
Why `false`:
|
||||
- Claude CLI runs directly on the host
|
||||
- it is not running inside the proxy container
|
||||
- no container-local base URL override is needed
|
||||
|
||||
Install to:
|
||||
|
||||
```bash
|
||||
/root/trigger-claude-refresh.sh
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
```bash
|
||||
chmod +x /root/trigger-claude-refresh.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 5 — Install Systemd Units
|
||||
|
||||
Use the repo's `templates/` directory as the base for these units:
|
||||
|
||||
- `sync-oauth-token.service`
|
||||
- `trigger-claude-refresh.service`
|
||||
- `trigger-claude-refresh.timer`
|
||||
|
||||
Substitute:
|
||||
|
||||
- `@@SYNC_SCRIPT_PATH@@` → `/root/sync-oauth-token.sh`
|
||||
- `@@TRIGGER_SCRIPT_PATH@@` → `/root/trigger-claude-refresh.sh`
|
||||
|
||||
Install them to:
|
||||
|
||||
```bash
|
||||
/etc/systemd/system/
|
||||
```
|
||||
|
||||
Then run:
|
||||
|
||||
```bash
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now sync-oauth-token.service
|
||||
systemctl enable --now trigger-claude-refresh.timer
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 6 — Configure the `claudehack` Provider
|
||||
|
||||
This is a **new provider** separate from OpenClaw’s built-in `anthropic` provider.
|
||||
|
||||
Do **not** modify existing provider identities beyond adding the new provider and related model entries.
|
||||
|
||||
Three separate configuration locations must be updated.
|
||||
|
||||
### 6.1 Global `openclaw.json` → `models.providers`
|
||||
|
||||
Add a new provider entry named:
|
||||
|
||||
```json
|
||||
"claudehack"
|
||||
```
|
||||
|
||||
Provider requirements:
|
||||
|
||||
- `baseUrl`: `"https://api.anthropic.com"`
|
||||
- `api`: `"anthropic-messages"`
|
||||
|
||||
Add two models:
|
||||
|
||||
1. `claude-opus-4-6`
|
||||
- name: `"ClaudeHack Opus 4.6"`
|
||||
- contextWindow: `200000`
|
||||
- maxTokens: `32000`
|
||||
- input: `["text", "image"]`
|
||||
- costs: all zero
|
||||
|
||||
2. `claude-sonnet-4-6`
|
||||
- name: `"ClaudeHack Sonnet 4.6"`
|
||||
- contextWindow: `200000`
|
||||
- maxTokens: `32000`
|
||||
- input: `["text", "image"]`
|
||||
- costs: all zero
|
||||
|
||||
### 6.2 Global `openclaw.json` → `agents.defaults.models`
|
||||
|
||||
Add these model registrations:
|
||||
|
||||
- `claudehack/claude-opus-4-6`
|
||||
- alias: `"ClaudeHack Opus 4.6"`
|
||||
|
||||
- `claudehack/claude-sonnet-4-6`
|
||||
- alias: `"ClaudeHack Sonnet 4.6"`
|
||||
|
||||
These are additive registrations only.
|
||||
|
||||
### 6.3 Per-agent `models.json`
|
||||
|
||||
For every agent directory:
|
||||
|
||||
```bash
|
||||
/root/.openclaw/agents/*/agent/models.json
|
||||
```
|
||||
|
||||
Add the same `claudehack` provider block to the file’s `providers` object.
|
||||
|
||||
If the file does not exist, create it.
|
||||
|
||||
Do not delete existing providers.
|
||||
|
||||
---
|
||||
|
||||
## Step 7 — Configure Auth Profiles
|
||||
|
||||
For **every**:
|
||||
|
||||
```bash
|
||||
/root/.openclaw/agents/*/agent/auth-profiles.json
|
||||
```
|
||||
|
||||
add a new profile entry.
|
||||
|
||||
If the file does not exist, create it.
|
||||
|
||||
Read the fresh token from:
|
||||
|
||||
```json
|
||||
claudeAiOauth.accessToken
|
||||
```
|
||||
|
||||
inside the Claude CLI credentials file.
|
||||
|
||||
### Required structure
|
||||
|
||||
Under `profiles`, add:
|
||||
|
||||
```json
|
||||
"claudehack:default": {
|
||||
"type": "oauth",
|
||||
"provider": "claudehack",
|
||||
"access": "<FRESH_TOKEN>"
|
||||
}
|
||||
```
|
||||
|
||||
Under `lastGood`, add:
|
||||
|
||||
```json
|
||||
"claudehack": "claudehack:default"
|
||||
```
|
||||
|
||||
Under `usageStats`, add:
|
||||
|
||||
```json
|
||||
"claudehack:default": {
|
||||
"errorCount": 0
|
||||
}
|
||||
```
|
||||
|
||||
Preserve all existing profile entries.
|
||||
|
||||
---
|
||||
|
||||
## Step 8 — Initial Sync and Verify
|
||||
|
||||
Restart the sync service to trigger the initial sync:
|
||||
|
||||
```bash
|
||||
systemctl restart sync-oauth-token.service
|
||||
```
|
||||
|
||||
Check logs:
|
||||
|
||||
```bash
|
||||
journalctl -u sync-oauth-token.service --since "1 min ago" --no-pager
|
||||
```
|
||||
|
||||
Expected successful behavior should include log output indicating:
|
||||
|
||||
- updated `oauth.json`
|
||||
- updated `.env`
|
||||
- updated `N` claudehack auth profiles
|
||||
- gateway recreated
|
||||
|
||||
### Verify service state
|
||||
|
||||
```bash
|
||||
systemctl is-active sync-oauth-token.service
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
```bash
|
||||
active
|
||||
```
|
||||
|
||||
Check timer registration:
|
||||
|
||||
```bash
|
||||
systemctl list-timers --all | grep trigger-claude-refresh
|
||||
```
|
||||
|
||||
Expected:
|
||||
- `trigger-claude-refresh.timer` is installed
|
||||
- next run time is visible
|
||||
|
||||
Check gateway container health:
|
||||
|
||||
```bash
|
||||
docker ps
|
||||
```
|
||||
|
||||
Confirm the OpenClaw gateway is up and healthy.
|
||||
|
||||
Check gateway logs for config reload / startup success and `claudehack` availability:
|
||||
|
||||
```bash
|
||||
docker logs "$GATEWAY_CONTAINER" --tail 200
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Critical Gotchas
|
||||
|
||||
These are mandatory. If any of these are wrong, the install may silently fail.
|
||||
|
||||
### 1. Auth profile field must be `access`, not `key`
|
||||
|
||||
Correct:
|
||||
|
||||
```json
|
||||
"access": "<TOKEN>"
|
||||
```
|
||||
|
||||
Wrong:
|
||||
|
||||
```json
|
||||
"key": "<TOKEN>"
|
||||
```
|
||||
|
||||
Using `key` causes OpenClaw to silently skip the profile.
|
||||
|
||||
---
|
||||
|
||||
### 2. Auth profile type must be `oauth`, not `token`
|
||||
|
||||
Correct:
|
||||
|
||||
```json
|
||||
"type": "oauth"
|
||||
```
|
||||
|
||||
Wrong:
|
||||
|
||||
```json
|
||||
"type": "token"
|
||||
```
|
||||
|
||||
Why:
|
||||
- `oauth` tells the gateway to attach Claude Code identity headers
|
||||
- without those headers, Anthropic rejects the request with errors like:
|
||||
|
||||
> "Third-party apps now draw from your extra usage"
|
||||
|
||||
---
|
||||
|
||||
### 3. The sync script must use `docker compose down` then `up`, not `restart`
|
||||
|
||||
Do **not** use:
|
||||
|
||||
```bash
|
||||
docker compose restart
|
||||
```
|
||||
|
||||
Use a full recreate flow so updated environment values are picked up.
|
||||
|
||||
Reason:
|
||||
- `restart` can reuse cached environment variables
|
||||
- the updated `ANTHROPIC_OAUTH_TOKEN` from `.env` may not be applied
|
||||
|
||||
---
|
||||
|
||||
### 4. `oauth.json` field mapping is different from Claude CLI credentials
|
||||
|
||||
Claude CLI credentials file uses:
|
||||
|
||||
- `accessToken`
|
||||
- `refreshToken`
|
||||
- `expiresAt`
|
||||
|
||||
OpenClaw `oauth.json` expects:
|
||||
|
||||
- `access`
|
||||
- `refresh`
|
||||
- `expires`
|
||||
|
||||
The sync script must translate these correctly.
|
||||
|
||||
---
|
||||
|
||||
### 5. All three model registration points are required
|
||||
|
||||
You must update all three:
|
||||
|
||||
1. global `models.providers`
|
||||
2. global `agents.defaults.models`
|
||||
3. per-agent `models.json`
|
||||
|
||||
If any of these are missing:
|
||||
- models may not appear in the UI
|
||||
- model selection may fail
|
||||
- requests may error with `"Unknown model"`
|
||||
|
||||
---
|
||||
|
||||
### 6. Do not set `claudehack` as primary or fallback defaults
|
||||
|
||||
This install is additive only.
|
||||
|
||||
The system’s existing primary/fallback models must remain unchanged unless explicitly requested by the human operator.
|
||||
|
||||
---
|
||||
|
||||
## Definition of Done
|
||||
|
||||
The install is complete only when **all** of the following are true:
|
||||
|
||||
1. Claude CLI is installed and authenticated on the host
|
||||
2. `~/.claude/.credentials.json` exists and contains valid OAuth data
|
||||
3. `/root/sync-oauth-token.sh` exists, is executable, and includes the `update-claudehack-profiles.py` call
|
||||
4. `/root/update-claudehack-profiles.py` exists and is executable
|
||||
5. `/root/trigger-claude-refresh.sh` exists and is executable
|
||||
6. all required systemd units are installed and enabled
|
||||
7. `claudehack` exists in global `openclaw.json`
|
||||
8. `claudehack` model aliases exist in global `agents.defaults.models`
|
||||
9. every agent has `claudehack` provider entries in `models.json`
|
||||
10. every agent has `claudehack:default` in `auth-profiles.json`
|
||||
11. sync service runs successfully
|
||||
12. timer is active
|
||||
13. gateway is healthy
|
||||
14. `claudehack/claude-opus-4-6` and `claudehack/claude-sonnet-4-6` are visible as optional models
|
||||
15. existing defaults and providers were preserved
|
||||
16. webhook security was not installed or modified
|
||||
|
||||
---
|
||||
|
||||
## Final Notes for the Installing Agent
|
||||
|
||||
- Be conservative.
|
||||
- Preserve existing config.
|
||||
- Make additive changes only.
|
||||
- Do not silently skip missing files; create them correctly.
|
||||
- Validate every file written.
|
||||
- Validate service state after installation.
|
||||
- Validate the gateway actually sees the new models.
|
||||
- Skip webhook security entirely.
|
||||
Reference in New Issue
Block a user