Adding a README.md so I can remember what I did with Claude :D
All checks were successful
Build and Push / build (push) Successful in 15s

This commit is contained in:
Joshua Adkisson
2026-04-02 11:56:17 -05:00
parent 28bdc24a6c
commit 4a16621255

326
README.md Normal file
View File

@@ -0,0 +1,326 @@
# OpenClaw + Claude Max API Proxy
All-in-one Docker container that runs [OpenClaw](https://github.com/openclaw/openclaw) powered by your Claude Max subscription through the [wende/claude-max-api-proxy](https://github.com/wende/claude-max-api-proxy) fork. No separate API key costs.
## Architecture
```
Discord / Telegram / WhatsApp
OpenClaw Gateway (:18789)
claude-max-api-proxy (:3456)
Claude Code CLI (OAuth)
Anthropic API (via Max subscription)
```
## Prerequisites
- A server running Docker (tested on Debian Trixie with CasaOS)
- A [Claude Max](https://claude.ai) subscription
- A Discord bot token (or Telegram/WhatsApp — see OpenClaw docs)
- Node.js 22+ is handled inside the container — no host dependency
## Container Image
The image is built via Gitea Actions and pushed to the Gitea Container Registry:
```
gitea.pitthappens.dyndns.org/ragincajunbanjo/openclaw-proxy:latest
```
---
## Deployment
### 1. Create data directories
```bash
sudo mkdir -p /DATA/AppData/openclaw/{claude,config,workspace}
sudo chown -R 1000:1000 /DATA/AppData/openclaw
```
### 2. Log into the Gitea container registry
```bash
docker login gitea.pitthappens.dyndns.org
```
Use your Gitea username and a personal access token with `package:read` scope.
### 3. Deploy the container
Use Docker Compose or paste into CasaOS Custom Install:
```yaml
services:
openclaw:
image: gitea.pitthappens.dyndns.org/ragincajunbanjo/openclaw-proxy:latest
container_name: openclaw
restart: unless-stopped
ports:
- "3456:3456"
- "18789:18789"
- "18790:18790"
volumes:
- /DATA/AppData/openclaw/claude:/home/node/.claude
- /DATA/AppData/openclaw/config:/home/node/.openclaw
- /DATA/AppData/openclaw/workspace:/home/node/.openclaw/workspace
environment:
- HOME=/home/node
- TERM=xterm-256color
- OPENCLAW_GATEWAY_BIND=lan
- OPENCLAW_GATEWAY_TOKEN=your-secure-token-here
- OPENAI_API_KEY=not-needed
- OPENAI_BASE_URL=http://127.0.0.1:3456/v1
- TZ=America/Chicago
healthcheck:
test: ["CMD", "curl", "-sf", "http://127.0.0.1:3456/health"]
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
init: true
```
Generate a secure gateway token with:
```bash
openssl rand -hex 32
```
### 4. Authenticate Claude Code (one-time)
The container will boot-loop until Claude is authenticated. Stop it first, then run auth in a one-off container:
```bash
docker stop openclaw
docker run -it --rm \
-v /DATA/AppData/openclaw/claude:/home/node/.claude \
gitea.pitthappens.dyndns.org/ragincajunbanjo/openclaw-proxy:latest \
/usr/local/bin/entrypoint.sh auth
```
This starts the Claude Code OAuth flow. You'll get a URL to open in your browser — sign in with your Claude Max account. Credentials are saved to the mounted volume and persist across container restarts.
Start the container after auth completes:
```bash
docker start openclaw
```
### 5. Configure OpenClaw
Edit the config file directly:
```bash
cat > /DATA/AppData/openclaw/config/openclaw.json << 'EOF'
{
"env": {
"OPENAI_API_KEY": "not-needed"
},
"models": {
"providers": {
"claude-proxy": {
"api": "openai-completions",
"baseUrl": "http://127.0.0.1:3456/v1",
"apiKey": "not-needed",
"models": [
{
"id": "claude-sonnet-4",
"name": "Claude Sonnet 4"
}
]
}
}
},
"agents": {
"defaults": {
"workspace": "/home/node/.openclaw/workspace",
"model": {
"primary": "claude-proxy/claude-sonnet-4"
}
}
},
"gateway": {
"mode": "local",
"bind": "lan"
}
}
EOF
```
To add more models (e.g. Opus), add entries to the `models` array:
```json
{
"id": "claude-opus-4",
"name": "Claude Opus 4"
}
```
Then set the primary model to `claude-proxy/claude-opus-4`.
Restart after editing config:
```bash
docker restart openclaw
```
### 6. Connect Discord
```bash
docker exec -it openclaw bash -c \
"cd /opt/openclaw && node dist/index.js channels add --channel discord --token YOUR_DISCORD_BOT_TOKEN"
```
Then DM or mention the bot on Discord. It will respond with a pairing code. Approve it:
```bash
docker exec openclaw bash -c \
"cd /opt/openclaw && node dist/index.js pairing approve discord YOUR_CODE"
```
Send another message — the bot should now respond.
### 7. Verify everything is working
```bash
# Check logs
docker logs -f openclaw
# Test the proxy directly
docker exec openclaw curl -s http://127.0.0.1:3456/health
# Test a completion
docker exec openclaw curl -s http://127.0.0.1:3456/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"claude-sonnet-4","messages":[{"role":"user","content":"Hello"}]}'
# Check OpenClaw status
docker exec openclaw bash -c "cd /opt/openclaw && node dist/index.js status"
```
---
## Updating
After a new image is built by CI:
```bash
docker pull gitea.pitthappens.dyndns.org/ragincajunbanjo/openclaw-proxy:latest
docker restart openclaw
```
Or from CasaOS, use the container's rebuild/update button.
Your config, credentials, and workspace are on persistent volumes and survive updates.
---
## CI/CD Pipeline
### Gitea Actions
The repo includes a workflow at `.gitea/workflows/build-deploy.yml` that builds the Docker image and pushes it to the Gitea Container Registry on every push to `main`.
### Required Gitea Setup
1. **Enable packages and actions** in Gitea's `app.ini`:
```ini
[packages]
ENABLED = true
[actions]
ENABLED = true
DEFAULT_ACTIONS_URL = https://github.com
```
Restart Gitea after editing.
2. **Install and register an Act Runner** on the server:
```bash
sudo wget -O /usr/local/bin/act_runner \
https://gitea.com/gitea/act_runner/releases/download/v0.2.11/act_runner-0.2.11-linux-amd64
sudo chmod +x /usr/local/bin/act_runner
sudo mkdir -p /opt/gitea-runner
cd /opt/gitea-runner
sudo act_runner register \
--instance https://gitea.pitthappens.dyndns.org \
--name local-runner \
--labels ubuntu-latest:host
```
Get the registration token from Gitea → Site Administration → Actions → Runners.
3. **Create a systemd service** for the runner:
```bash
sudo tee /etc/systemd/system/gitea-runner.service << 'SVCEOF'
[Unit]
Description=Gitea Act Runner
After=docker.service
Requires=docker.service
[Service]
Type=simple
User=root
WorkingDirectory=/opt/gitea-runner
ExecStart=/usr/local/bin/act_runner daemon
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
SVCEOF
sudo systemctl daemon-reload
sudo systemctl enable --now gitea-runner
```
4. **Add repo secrets** (Repo → Settings → Actions → Secrets):
- `REGISTRY_TOKEN` — Gitea personal access token with `package:write` scope
- `DOCKERHUB_USERNAME` — Docker Hub username (avoids pull rate limits during builds)
- `DOCKERHUB_TOKEN` — Docker Hub access token
---
## Persistent Volumes
| Host Path | Container Path | Purpose |
|---|---|---|
| `/DATA/AppData/openclaw/claude` | `/home/node/.claude` | Claude Code OAuth credentials |
| `/DATA/AppData/openclaw/config` | `/home/node/.openclaw` | OpenClaw settings and memory |
| `/DATA/AppData/openclaw/workspace` | `/home/node/.openclaw/workspace` | Agent working directory |
---
## Troubleshooting
| Problem | Solution |
|---|---|
| Container boot-loops with "No Claude credentials" | Run the one-off auth container (Step 4) |
| "Unknown model" on startup | Ensure `models.providers` is defined in `openclaw.json` with the correct structure (Step 5) |
| Proxy returns `[object Object]` | You may have the broken original npm package — rebuild with `--no-cache` |
| OAuth token expired | Re-run the auth step: `docker run -it --rm -v /DATA/AppData/openclaw/claude:/home/node/.claude <image> /usr/local/bin/entrypoint.sh auth` |
| Discord bot doesn't respond | Check pairing: `docker exec openclaw bash -c "cd /opt/openclaw && node dist/index.js pairing list"` and approve any pending codes |
| "Control UI build failed" in logs | Cosmetic only — the gateway works fine without it |
| Docker Hub rate limit during CI build | Add `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN` secrets to the repo |
| OpenClaw requires Node >= 22 | Make sure the Dockerfile uses `node:22-bookworm-slim` as the base image |
| `env: node: No such file or directory` | Background services (LaunchAgent/systemd) don't inherit shell PATH — use full paths to `node` |
---
## Important Notes
- The `claude-max-api-proxy` is a **community tool**, not officially supported by Anthropic or OpenClaw. It wraps the Claude Code CLI to expose an OpenAI-compatible API using your Max subscription's OAuth credentials.
- The proxy binds to `127.0.0.1:3456` inside the container. Port 3456 is exposed for debugging but the proxy is only used internally by OpenClaw.
- This setup uses the [wende fork](https://github.com/wende/claude-max-api-proxy) which fixes a serialization bug in the original package that caused responses to return `[object Object]`.