|
| 1 | +# Building and deploying a custom CLIProxyAPI binary |
| 2 | + |
| 3 | +When a new model (e.g. `claude-opus-4.7`) is released before the upstream |
| 4 | +[`router-for-me/CLIProxyAPI`](https://github.com/router-for-me/CLIProxyAPI) ships it, |
| 5 | +you can build your own binary with the model added. |
| 6 | + |
| 7 | +## Where the model list lives |
| 8 | + |
| 9 | +CLIProxyAPI resolves its model catalog in this order: |
| 10 | + |
| 11 | +1. **Remote** (wins on startup): |
| 12 | + `https://raw.githubusercontent.com/router-for-me/models/refs/heads/main/models.json` |
| 13 | + and `https://models.router-for.me/models.json`. |
| 14 | + URLs are hard-coded in `internal/registry/model_updater.go` (`modelsURLs`). |
| 15 | +2. **Embedded fallback**: `internal/registry/models/models.json` |
| 16 | + (embedded into the binary via `//go:embed`). |
| 17 | + |
| 18 | +Because the remote list overrides the embedded one, **adding a model to the embedded |
| 19 | +JSON alone is not enough** — you must either: |
| 20 | + |
| 21 | +- Get the model merged into [`router-for-me/models`](https://github.com/router-for-me/models), **or** |
| 22 | +- Point `modelsURLs` at your own fork. |
| 23 | + |
| 24 | +## Deploy location |
| 25 | + |
| 26 | +On our dev box the binary lives at: |
| 27 | + |
| 28 | +``` |
| 29 | +~/cliproxyapi/cli-proxy-api |
| 30 | +``` |
| 31 | + |
| 32 | +and is run via the user systemd unit `cliproxyapi.service` |
| 33 | +(`~/.config/systemd/user/cliproxyapi.service`), listening on port `8317` |
| 34 | +(see `~/cliproxyapi/config.yaml`). |
| 35 | + |
| 36 | +## Procedure for adding a new model |
| 37 | + |
| 38 | +### 1. Fork + update `router-for-me/models` |
| 39 | + |
| 40 | +```bash |
| 41 | +cd ~/repo/awesome |
| 42 | +git clone https://github.com/router-for-me/models.git # if not already cloned |
| 43 | +cd models |
| 44 | +gh repo fork --remote=true # creates Sixzero/models, sets origin to the fork |
| 45 | +git checkout -b add-<model-id> |
| 46 | +``` |
| 47 | + |
| 48 | +Add the new entry to `models.json` (mirror the closest existing model, e.g. copy the |
| 49 | +`claude-opus-4-6` block and adjust `id`, `display_name`, `created`): |
| 50 | + |
| 51 | +```json |
| 52 | +{ |
| 53 | + "id": "claude-opus-4-7", |
| 54 | + "object": "model", |
| 55 | + "created": 1776643200, |
| 56 | + "owned_by": "anthropic", |
| 57 | + "type": "claude", |
| 58 | + "display_name": "Claude 4.7 Opus", |
| 59 | + "description": "Premium model combining maximum intelligence with practical performance", |
| 60 | + "context_length": 1000000, |
| 61 | + "max_completion_tokens": 128000, |
| 62 | + "thinking": { |
| 63 | + "min": 1024, "max": 128000, "zero_allowed": true, |
| 64 | + "levels": ["low", "medium", "high", "max"] |
| 65 | + } |
| 66 | +} |
| 67 | +``` |
| 68 | + |
| 69 | +Then: |
| 70 | + |
| 71 | +```bash |
| 72 | +git commit -am "Add <model-id>" |
| 73 | +git push origin add-<model-id> |
| 74 | +gh pr create --repo router-for-me/models --title "Add <model-id>" \ |
| 75 | + --body "Mirrors the previous entry." --head Sixzero:add-<model-id> |
| 76 | +``` |
| 77 | + |
| 78 | +Once the PR is merged, CLIProxyAPI will pick the new model up on its next refresh |
| 79 | +(every 3 hours) or on restart — no rebuild needed. |
| 80 | + |
| 81 | +### 2. (Until the PR merges) Build a custom binary pointing at your fork |
| 82 | + |
| 83 | +```bash |
| 84 | +cd ~/repo/awesome/CLIProxyAPI |
| 85 | +git pull |
| 86 | +``` |
| 87 | + |
| 88 | +Edit `internal/registry/model_updater.go` and prepend your fork URL to `modelsURLs`: |
| 89 | + |
| 90 | +```go |
| 91 | +var modelsURLs = []string{ |
| 92 | + "https://raw.githubusercontent.com/Sixzero/models/refs/heads/add-<model-id>/models.json", |
| 93 | + "https://raw.githubusercontent.com/router-for-me/models/refs/heads/main/models.json", |
| 94 | + "https://models.router-for.me/models.json", |
| 95 | +} |
| 96 | +``` |
| 97 | + |
| 98 | +Optional: also add the model to the embedded fallback |
| 99 | +(`internal/registry/models/models.json`) so offline startups work. |
| 100 | + |
| 101 | +Build: |
| 102 | + |
| 103 | +```bash |
| 104 | +go build -o ~/cliproxyapi/cli-proxy-api-new ./cmd/server/ |
| 105 | +``` |
| 106 | + |
| 107 | +### 3. Swap and restart |
| 108 | + |
| 109 | +```bash |
| 110 | +# Back up the current binary |
| 111 | +cp ~/cliproxyapi/cli-proxy-api ~/cliproxyapi/cli-proxy-api.bak |
| 112 | + |
| 113 | +# Install the new one |
| 114 | +mv ~/cliproxyapi/cli-proxy-api-new ~/cliproxyapi/cli-proxy-api |
| 115 | + |
| 116 | +# Restart the service |
| 117 | +systemctl --user restart cliproxyapi.service |
| 118 | +sleep 3 |
| 119 | +systemctl --user status cliproxyapi.service --no-pager |
| 120 | +``` |
| 121 | + |
| 122 | +### 4. Verify the model is listed |
| 123 | + |
| 124 | +```bash |
| 125 | +curl -s http://localhost:8317/v1/models \ |
| 126 | + -H "Authorization: Bearer $CLIPROXYAPI_API_KEY" \ |
| 127 | + | python3 -c "import sys,json; [print(m['id']) for m in json.load(sys.stdin).get('data',[])]" \ |
| 128 | + | grep <model-id> |
| 129 | +``` |
| 130 | + |
| 131 | +Startup log should contain: |
| 132 | + |
| 133 | +``` |
| 134 | +model_updater.go:134 startup model refresh completed from https://raw.githubusercontent.com/Sixzero/models/... |
| 135 | +``` |
| 136 | + |
| 137 | +### 5. Add the OpenRouter model mapping |
| 138 | + |
| 139 | +In `OpenRouterCLIProxyAPI.jl/src/OpenRouterCLIProxyAPI.jl`, add the mapping so the |
| 140 | +package can translate `anthropic/<model>` (OpenRouter-style) to the proxy's |
| 141 | +native ID: |
| 142 | + |
| 143 | +```julia |
| 144 | +const MODEL_MAP_ANTHROPIC = Dict{String,String}( |
| 145 | + ... |
| 146 | + "claude-opus-4-7" => "anthropic/claude-opus-4.7", # LATEST Anthropic model - UPDATE ON NEW RELEASE |
| 147 | + ... |
| 148 | +) |
| 149 | +``` |
| 150 | + |
| 151 | +### 6. Revert the URL override once upstream merges |
| 152 | + |
| 153 | +After `router-for-me/models` merges your PR, revert the `modelsURLs` change in |
| 154 | +`model_updater.go` and rebuild so we're back on the upstream feed. |
| 155 | + |
| 156 | +## Rollback |
| 157 | + |
| 158 | +If something goes wrong: |
| 159 | + |
| 160 | +```bash |
| 161 | +mv ~/cliproxyapi/cli-proxy-api.bak ~/cliproxyapi/cli-proxy-api |
| 162 | +systemctl --user restart cliproxyapi.service |
| 163 | +``` |
| 164 | + |
| 165 | +## Handing this off to an operator |
| 166 | + |
| 167 | +Give them: |
| 168 | + |
| 169 | +1. This document. |
| 170 | +2. The built binary (`~/cliproxyapi/cli-proxy-api-new`) — or build instructions above. |
| 171 | +3. The deploy target: `~/cliproxyapi/cli-proxy-api` on the server. |
| 172 | +4. The restart command: `systemctl --user restart cliproxyapi.service`. |
| 173 | +5. The verify command from step 4. |
0 commit comments