echo "This page is instructions for an AI coding agent to read, not a script to run. Nothing was run."; exit 1
<!-- Line 1 stops any shell this page is piped into, and the '<' that starts this line stops PowerShell. -->
# Runbook: SolCard Inference in Claude Code, next to the user's Claude models

Read this with your shell (`curl -fsSL https://api.solcardinference.ai/install/claude-code`), not a fetch tool that summarizes: the commands below must be exact. On native Windows (your environment says `win32`), follow `https://api.solcardinference.ai/install/claude-code/windows` instead.

You're Claude Code, and the user asked you to add SolCard Inference to their models. When you're done, Claude Code keeps the user's own Claude models on their own Claude plan, and `/model` lists SolCard Inference's models below them. A small local proxy, [CLIProxyAPI](https://github.com/router-for-me/CLIProxyAPI) (open source), sends each request to the right place. It runs on `127.0.0.1` only, as a login service, behind a key only this machine has. Claude requests go on to Anthropic with the user's own Claude Code login, exactly as Claude Code sends it: the proxy never holds, copies or refreshes that login. This is the setup Anthropic's Claude Code documentation describes for a gateway that keeps the user's subscription (step 1 has the page). The user approves one thing in the browser: SolCard Inference.

How to follow this runbook:
- Do the steps in order. Each one says what to run and what you should see. If you see something else, follow that step's **If not** line. If none fits, tell the user what you saw, in one or two sentences, and stop.
- Run each command exactly as written, in your shell tool. Replace only the parts in `<angle brackets>`.
- Never print a key or token. Don't `cat` `solcard.key` or anything under `auth/`. The commands here keep them in files.
- Change only the files named here, and keep the user's other settings exactly as they are.
- Everything lives in `~/.solcard-inference`. If a step fails halfway, run it again from its first command; every step is safe to repeat.
- If Claude Code's auto mode denies a command, that command didn't run. Tell the user which step it was and what it changes, and ask with your question tool whether to run it. If they say yes, run the same command once more. If it's denied again, they can allow it themselves in `/permissions`, under Recently blocked; when they say they have, run it again.

## Step 0. Check where you're running

```sh
echo "entrypoint=${CLAUDE_CODE_ENTRYPOINT:-none} cowork=${CLAUDE_CODE_IS_COWORK:-0}"; grep -qsE '"remoteControlAtStartup" *: *true' ~/.claude/settings.json && echo "remote control: on"; true
```

- **If you see `cowork=1` or `entrypoint=local-agent`:** you're in Claude Cowork. Cowork runs in a sandbox and picks its models from the user's Claude account, so nothing set up from here reaches it. Don't download or change anything. Tell the user, in these words, and stop:
  > Cowork only runs Claude's own models, and it can't add others, so I can't set up SolCard Inference from here. It works in Claude Code in a terminal: open a terminal app, run `claude`, and paste the same sentence there.
- **If `entrypoint=` starts with `claude-desktop`:** you're in the Claude desktop app's Code tab. The app starts these sessions with its own connection to Anthropic and ignores the settings this runbook writes, so SolCard's models won't appear in this app. Ask the user, in these words, and wait:
  > The Claude desktop app's Code tab only runs Claude's own models, so SolCard Inference can't appear here. I can set it up for Claude Code in your terminal on this computer instead; this app keeps working as it does now. Want me to do that?
  - **If they say yes:** go on with step 1, and use the desktop wording in step 10.
  - **If they say no:** stop.
- **`remote control: on`** means the user has Remote Control start with every session. Claude Code doesn't offer Remote Control while it talks to a custom API address like this proxy's, so step 1's question says so. If that line isn't there, don't mention Remote Control.

## Step 1. Ask once

Ask with your question tool (AskUserQuestion), so the user answers in Claude Code's own dialog; if you don't have that tool, ask in your reply. If you want to tell them more first, such as what you've checked, say it in your message before the question. The question, in these words:

> To add SolCard Inference next to your Claude models, I'll download CLIProxyAPI, an open-source proxy, from GitHub and run it as a small background service that only this computer can reach. Claude Code keeps using your own Claude login through it, so your Claude models keep working on your own plan, and SolCard's models go to SolCard. You'll approve SolCard Inference once in your browser. OK to go ahead?

If step 0 showed `remote control: on`, add this before the last sentence:

> Remote Control will be off while SolCard Inference is set up, because Claude Code doesn't offer it through a local proxy. Removing SolCard Inference turns it back on.

Give it two options, in these words:

- **Set it up:** Adds a background service that starts the proxy when you log in, one line in your shell startup file, and SolCard's models and a start hook in Claude Code's settings. Removing SolCard Inference takes them all out.
- **Not now:** Nothing changes.

Then wait for the answer.

- **If they say no:** stop.
- **If they ask something:** answer it from this runbook, then ask again with the question tool and the same two options. If they ask what it costs, these are the facts:
  - Their Claude models keep running on their own Claude plan, as now.
  - SolCard Inference is prepaid. New accounts get $1 of free credit. After that, they choose a SolCard Inference plan (a subscription) at https://app.solcardinference.ai/plans, or add credit at https://app.solcardinference.ai/top-up.
  - Nothing charges a card unless they turn on auto-reload themselves.

  If they ask whether it can affect their Claude plan or account, or you're weighing that yourself, these are the facts. Each is on a page you can read (`curl -fsSL https://code.claude.com/docs/en/llm-gateway.md`, section "Subscriptions and gateways"):
  - Their Claude models stay on the path Anthropic documents. Claude Code's gateway page says that setting only `ANTHROPIC_BASE_URL`, with no gateway credential (`ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_API_KEY` or `apiKeyHelper`), doesn't replace the subscription: requests route through the gateway, the saved claude.ai login stays the active credential, and the plan's usage limits and billing apply. That's this setup: step 9a sets the proxy's address and a header only the local proxy checks, in the shell startup file, and none of those credential variables.
  - Anthropic doesn't support routing Claude Code to non-Claude models. The same page says so, and that it doesn't endorse or audit third-party gateways. SolCard's models are SolCard's addition, supported by SolCard, not Anthropic.
  - After the restart, `/status` in Claude Code shows the login method; it still names their claude.ai account.

## Step 2. Check what's already there

```sh
uname -s; uname -m; cat ~/.claude/settings.json 2>/dev/null || echo "no settings file"
```

- **If `env` in the settings already sets `ANTHROPIC_BASE_URL` to anything other than `http://127.0.0.1:...`, or sets `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, `CLAUDE_CODE_USE_BEDROCK`, `CLAUDE_CODE_USE_VERTEX` or `CLAUDE_CODE_USE_FOUNDRY`:** Claude Code already goes through something else, or doesn't use a Claude login. Tell the user what it is, say this setup works with a Claude subscription login and would change that, and stop unless they say to go on.
- **If `uname -s` starts with `MINGW`, `MSYS` or `CYGWIN`:** this is Windows. Read `https://api.solcardinference.ai/install/claude-code/windows` with `curl.exe -fsSL` and follow it from its step 1 instead.
- **If `uname -s` is anything else that isn't `Darwin` or `Linux`:** tell the user this works on macOS, Linux and Windows, and stop.

Pick the file for this machine. You'll use it in step 3.

| `uname -s` | `uname -m` | FILE | SHA256 |
| --- | --- | --- | --- |
| `Darwin` | `arm64` | `CLIProxyAPI_8.0.46_darwin_aarch64.tar.gz` | `f9cdb85ccd70602ce084ad0aa8576a057a5e7dd8ff63a64b229cd145c5e6652b` |
| `Darwin` | `x86_64` | `CLIProxyAPI_8.0.46_darwin_amd64.tar.gz` | `bf8ba3bd1990e115bfba6f61a93d83233974a5457540ebdd03df69d142f14efb` |
| `Linux` | `x86_64` | `CLIProxyAPI_8.0.46_linux_amd64.tar.gz` | `471f5235c501c19d3dec85c06e7612f0fe5ce3f823ef75331c2097aad8ed3c62` |
| `Linux` | `aarch64` | `CLIProxyAPI_8.0.46_linux_aarch64.tar.gz` | `07b792e0d2eedb46fcb6c9d1eda913b4c53413076a03199346a85a573fd00de7` |

## Step 3. Download CLIProxyAPI 8.0.46 and check it

Replace `<FILE>` and `<SHA256>` with the row from step 2:

```sh
mkdir -p ~/.solcard-inference/auth && chmod 700 ~/.solcard-inference ~/.solcard-inference/auth && cd ~/.solcard-inference && curl -fsSL -o cpa.tar.gz "https://github.com/router-for-me/CLIProxyAPI/releases/download/v8.0.46/<FILE>" && got=$({ sha256sum cpa.tar.gz 2>/dev/null || shasum -a 256 cpa.tar.gz; } | cut -d' ' -f1) && if [ "$got" = "<SHA256>" ]; then tar -xzf cpa.tar.gz cli-proxy-api && rm cpa.tar.gz && chmod 755 cli-proxy-api && echo "checksum ok"; else rm cpa.tar.gz; echo "CHECKSUM MISMATCH: $got"; fi
```

- **You should see:** `checksum ok`.
- **If you see `CHECKSUM MISMATCH`:** stop, and tell the user the download didn't match the published checksum. Don't run anything you downloaded.

## Step 4. A port and a local key

```sh
cd ~/.solcard-inference && if [ ! -s port ]; then for p in 18317 18318 18319 18320; do curl -s -o /dev/null --connect-timeout 1 "http://127.0.0.1:$p/"; if [ $? -eq 7 ]; then echo "$p" > port; break; fi; done; fi; [ -s local.key ] || (umask 077; od -An -tx1 -N24 /dev/urandom | tr -d ' \n' > local.key); echo "port $(cat port)"
```

- **You should see:** `port ` and a number.
- **If no number is printed:** the ports 18317 18318 18319 18320 are all busy. Tell the user, and stop.

## Step 5. Start the SolCard approval

If the user's message included a SolCard Inference key (it starts with `sk-si-`), write it now with your file-editing tool to `~/.solcard-inference/solcard.key`, containing only the key. Then run `chmod 600 ~/.solcard-inference/solcard.key`, and go straight to step 7.

```sh
cd ~/.solcard-inference && curl -fsS -X POST "https://api.solcardinference.ai/v1/connect" -H 'content-type: application/json' -d "{\"client\":\"claude-code\",\"device\":\"$(hostname | cut -c1-40)\"}" -o connect.json && chmod 600 connect.json && sed -n 's/.*"verification_uri_complete":"\([^"]*\)".*/\1/p' connect.json && sed -n 's/.*"user_code":"\([^"]*\)".*/\1/p' connect.json
```

- **You should see:** a link starting `https://app.solcardinference.ai/connect?code=`, then the code.
- **If not:** show the user the error line, and stop.

Tell the user, with the real link and code, the link in full on its own line (they click it in your message):

> Approve SolCard Inference in your browser: `<the link>`
> Sign up or sign in, check the code is `<the code>`, and click Approve. Tell me when it's done.

Then wait for the user.

## Step 6. Collect the SolCard key

It waits up to 45 seconds for the approval:

```sh
cd ~/.solcard-inference && curl -s -X POST "https://api.solcardinference.ai/v1/connect/token" -H 'content-type: application/json' -d "{\"device_code\":\"$(sed -n 's/.*"device_code":"\([^"]*\)".*/\1/p' connect.json)\",\"wait\":45}" > token.json; if grep -q '"api_key"' token.json; then (umask 077; sed -n 's/.*"api_key":"\([^"]*\)".*/\1/p' token.json > solcard.key); rm -f token.json connect.json; echo "solcard ok"; else cat token.json; rm -f token.json; fi
```

- **You should see:** `solcard ok`.
- **If you see `authorization_pending`:** the user hasn't approved yet. Ask them to finish the SolCard page, then run step 6 again.
- **If you see `expired_token` or `access_denied`:** run step 5 again, give the user the new link and code, and when they say done, run step 6 again.

## Step 7. Run the proxy at login

This writes the proxy's config and its Claude entry. Where each request goes, so you can check it in these two files and in CLIProxyAPI 8.0.46's source:

- `api-keys: claude:` lists Anthropic-format API providers. Its one entry is SolCard. Because the entry lists `models`, it serves only those `solcard-inference-*` names (`sdk/cliproxy/service_models.go`), and only those requests get its `base-url` and the SolCard key.
- Every Claude model (CLIProxyAPI's built-in Claude list, `internal/registry/model_definitions.go`) uses `auth/claude-code-login.json`. It sets no base URL, so the proxy sends those requests to its default, `https://api.anthropic.com` (`internal/runtime/executor/claude_executor_execute.go`).
- That file holds no login. Its `access_token` is a placeholder the proxy needs to load the entry, and `"Authorization": "$Authorization"` replaces it on each request with the `Authorization` header Claude Code put on that request (`internal/util/header_helpers.go`). With no refresh token, the proxy never refreshes it (`internal/runtime/executor/claude_executor_auth.go`); Claude Code keeps refreshing its own login as it always has.
- `disable-cooling` on the SolCard entry keeps one failed SolCard request from blocking the next ones for minutes; `disable_cooling` and `request_scoped_errors` keep one refused Claude login (say, one that just expired) from blocking the next requests: otherwise CLIProxyAPI marks the file's own entry refused and answers 503 to every later Claude request until it restarts (`sdk/cliproxy/auth/conductor_refresh.go`).
- Request logging (`request-log`) is off by default, and this config doesn't turn it on.

```sh
cd ~/.solcard-inference && umask 077 && cat > config.yaml <<EOF
config-version: 8
server:
  host: "127.0.0.1"
  port: $(cat port)
management:
  allow-remote: false
  secret-key: ""
  disable-control-panel: true
access:
  api-keys:
    - "$(cat local.key)"
oauth:
  auth-dir: "$HOME/.solcard-inference/auth"
api-keys:
  claude:
    - name: solcard-inference
      base-url: "https://api.solcardinference.ai"
      disable-cooling: true
      models:
        - name: "solcard-inference-large"
          alias: "solcard-inference-large"
          thinking:
            zero-allowed: true
            dynamic-allowed: true
            levels: ["low", "medium", "high", "xhigh", "max"]
        - name: "solcard-inference-fast"
          alias: "solcard-inference-fast"
          thinking:
            zero-allowed: true
            dynamic-allowed: true
            levels: ["low", "medium", "high", "xhigh", "max"]
        - name: "solcard-inference-base"
          alias: "solcard-inference-base"
          thinking:
            zero-allowed: true
            dynamic-allowed: true
            levels: ["low", "medium", "high", "xhigh", "max"]
        - name: "solcard-inference-large-legacy"
          alias: "solcard-inference-large-legacy"
          thinking:
            zero-allowed: true
            dynamic-allowed: true
            levels: ["low", "medium", "high", "xhigh", "max"]
        - name: "solcard-inference-pro"
          alias: "solcard-inference-pro"
          thinking:
            zero-allowed: true
            dynamic-allowed: true
            levels: ["low", "medium", "high", "xhigh", "max"]
        - name: "solcard-inference-lite"
          alias: "solcard-inference-lite"
          thinking:
            zero-allowed: true
            dynamic-allowed: true
            levels: ["low", "medium", "high", "xhigh", "max"]
        - name: "solcard-inference-hy4"
          alias: "solcard-inference-hy4"
          thinking:
            zero-allowed: true
            dynamic-allowed: true
            levels: ["low", "medium", "high", "xhigh", "max"]
      keys:
        - api-key: "$(cat solcard.key)"
EOF
chmod 600 config.yaml && printf '{\n  "type": "claude",\n  "email": "claude-code-login@this-machine",\n  "access_token": "sk-ant-oat01-uses-the-callers-own-login",\n  "refresh_token": "",\n  "expired": "2099-01-01T00:00:00Z",\n  "skip_account_profile": true,\n  "headers": { "Authorization": "$Authorization" },\n  "disable_cooling": true,\n  "request_scoped_errors": [\n    { "status": 401, "match-regexr": ["(?s).*"], "action": "stop" },\n    { "status": 403, "match-regexr": ["(?s).*"], "action": "stop" },\n    { "status": 429, "match-regexr": ["(?s).*"], "action": "stop" }\n  ]\n}\n' > auth/claude-code-login.json && chmod 600 auth/claude-code-login.json && cat > start.sh <<'START' && chmod 700 start.sh
#!/bin/sh
# Claude Code runs this when a session starts (the SessionStart hook in ~/.claude/settings.json): it starts the
# proxy if nothing answers on its port, and waits up to 5 seconds for it. Otherwise it does nothing.
cd ~/.solcard-inference 2>/dev/null || exit 0
up() { curl -s -o /dev/null --connect-timeout 1 "http://127.0.0.1:$(cat port)/"; [ $? -ne 7 ]; }
up && exit 0
(nohup ./cli-proxy-api -config config.yaml >> proxy.log 2>&1 < /dev/null &)
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25; do up && exit 0; sleep 0.2; done
exit 0
START
echo "config ok"
```

Then start it at login. Run only the block for this machine.

**Linux:**

```sh
mkdir -p ~/.config/systemd/user && printf '[Unit]\nDescription=SolCard Inference local proxy (CLIProxyAPI 8.0.46)\n[Service]\nExecStart=%%h/.solcard-inference/cli-proxy-api -config %%h/.solcard-inference/config.yaml\nRestart=on-failure\nRestartSec=2\n[Install]\nWantedBy=default.target\n' > ~/.config/systemd/user/solcard-inference-proxy.service && systemctl --user daemon-reload && systemctl --user enable solcard-inference-proxy.service && systemctl --user restart solcard-inference-proxy.service && sleep 3 && systemctl --user is-active solcard-inference-proxy.service
```

- **You should see:** `active`.
- **If `systemctl` says it can't connect to a bus** (some WSL and container setups have no user services): run `sh ~/.solcard-inference/start.sh` to start the proxy now, and carry on. After a restart, Claude Code starts it again each time it starts (the hook in step 9b).

**macOS:**

```sh
mkdir -p ~/Library/LaunchAgents && P=~/Library/LaunchAgents/ai.solcardinference.proxy.plist && printf '<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n<plist version="1.0"><dict><key>Label</key><string>ai.solcardinference.proxy</string><key>ProgramArguments</key><array><string>%s/.solcard-inference/cli-proxy-api</string><string>-config</string><string>%s/.solcard-inference/config.yaml</string></array><key>RunAtLoad</key><true/><key>KeepAlive</key><true/><key>StandardOutPath</key><string>%s/.solcard-inference/proxy.log</string><key>StandardErrorPath</key><string>%s/.solcard-inference/proxy.log</string></dict></plist>\n' "$HOME" "$HOME" "$HOME" "$HOME" > "$P" && (launchctl bootout "gui/$(id -u)/ai.solcardinference.proxy" 2>/dev/null; true) && launchctl bootstrap "gui/$(id -u)" "$P" && sleep 3 && launchctl print "gui/$(id -u)/ai.solcardinference.proxy" | grep -m1 'state ='
```

- **You should see:** `state = running`.

## Step 8. Check the proxy

```sh
cd ~/.solcard-inference && curl -s -m 20 "http://127.0.0.1:$(cat port)/v1/models" -H "Authorization: Bearer $(cat local.key)" | grep -o '"id":"[^"]*"' | grep -c -E '"id":"(claude-(opus|sonnet|fable)|solcard-inference-fast)' ; printf 'solcard-inference-fast: '; curl -s -o /dev/null -w '%{http_code}\n' -m 90 "http://127.0.0.1:$(cat port)/v1/messages" -H "Authorization: Bearer $(cat local.key)" -H 'content-type: application/json' -H 'anthropic-version: 2023-06-01' -d '{"model":"solcard-inference-fast","max_tokens":16,"messages":[{"role":"user","content":"Reply with: ok"}]}'
```

- **You should see:** a number of at least 4, then `solcard-inference-fast: 200`. The Claude models are listed but can't be tried from here: they answer with the user's Claude Code login, which only Claude Code sends.
- **If the first line is empty or `0`, or the second shows `000`:** the proxy isn't up yet. Wait five seconds and run it again.
- **If you see `402`:** the account has no credit: the $1 of free credit new accounts get is used up, or this account didn't get it. Offer a SolCard Inference plan first, with its page, https://app.solcardinference.ai/plans; adding prepaid credit at https://app.solcardinference.ai/top-up is the other way. Then carry on: SolCard's models answer once there's credit.
- **Any other code:** tell the user, and stop.

## Step 9. Point Claude Code at the proxy

Two parts:
- The proxy's address and key go in the user's shell startup file, so they reach Claude Code started from a terminal and nothing else. Claude's desktop app starts Claude Code its own way, and the proxy's key must never travel with those requests to Anthropic.
- SolCard's rows go in Claude Code's settings, with a start hook: when a Claude Code session starts, it runs `~/.solcard-inference/start.sh`, which starts the proxy if it isn't running (say, on a machine without a login service, or right after a restart).

**9a. The shell:**

```sh
cd ~/.solcard-inference && printf 'export ANTHROPIC_BASE_URL="http://127.0.0.1:%s"\nexport ANTHROPIC_CUSTOM_HEADERS="X-Api-Key: %s"\n' "$(cat port)" "$(cat local.key)" > env.sh && chmod 600 env.sh && for f in ~/.bashrc ~/.zshrc; do case "$f:$SHELL" in *bashrc:*bash|*zshrc:*zsh) touch "$f";; esac; if [ -f "$f" ]; then grep -q 'solcard-inference/env.sh' "$f" || printf '\n[ -f ~/.solcard-inference/env.sh ] && . ~/.solcard-inference/env.sh  # SolCard Inference\n' >> "$f"; echo "set in $f"; fi; done
```

- **You should see:** `set in` and the user's shell file (`.bashrc`, `.zshrc` or both).

**9b. The picker rows and the start hook.** With your file-editing tool, edit `~/.claude/settings.json` (`$CLAUDE_CONFIG_DIR/settings.json` if that variable is set). Create the file if it doesn't exist. Merge in exactly this:

```json
{
  "modelPicker": {
    "options": [
      {
        "model": "solcard-inference-large",
        "label": "SolCard Inference Large",
        "description": "Most capable. Built on GLM-5.3"
      },
      {
        "model": "solcard-inference-fast",
        "label": "SolCard Inference Fast",
        "description": "Fastest. Built on DeepSeek V4.1 Flash"
      },
      {
        "model": "solcard-inference-base",
        "label": "SolCard Inference Base",
        "description": "Everyday tasks"
      },
      {
        "model": "solcard-inference-large-legacy",
        "label": "SolCard Inference Large (legacy)",
        "description": "The previous Large. Built on GLM-5.2"
      },
      {
        "model": "solcard-inference-pro",
        "label": "SolCard Inference Pro",
        "description": "Best at security work. Built on Kimi K3.1 Pro"
      },
      {
        "model": "solcard-inference-lite",
        "label": "SolCard Inference Lite",
        "description": "Cheapest. Built on GLM-5.3 Flash"
      },
      {
        "model": "solcard-inference-hy4",
        "label": "SolCard Inference Hy4",
        "description": "Long agent runs. Built on Tencent Hy4"
      }
    ]
  },
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "sh ~/.solcard-inference/start.sh"
          }
        ]
      }
    ]
  }
}
```

- If `modelPicker.options` already exists, add these rows after the existing ones, skipping any `model` already listed.
- If `hooks.SessionStart` already exists, add this entry after the existing ones, unless one already runs `~/.solcard-inference/start.sh`.
- Don't set `replaceBuiltInOptions`, don't change `model`, and don't add anything to `env`. The user's Claude models stay as they are.
- Keep everything else in the file exactly as it is.

Then:

```sh
grep -c 'solcard-inference' ~/.claude/settings.json
```

- **You should see:** a number of at least 7.

## Step 10. Tell the user

> SolCard Inference is set up. Restart Claude Code in a new terminal: type `/exit`, open a new terminal window or tab, and run `claude` there. `/model` lists your Claude models, and below them SolCard Inference Large, Fast, Base and Large (legacy). Your Claude models keep running on your own plan and your own login.

If step 0 found the desktop app's Code tab, say this instead:

> SolCard Inference is set up for Claude Code in your terminal. Open a terminal app, or the Terminal pane of a Code session in this app, and run `claude`. `/model` lists your Claude models, and below them SolCard Inference Large, Fast, Base and Large (legacy). The desktop app's own Code and Cowork tabs stay as they are.

The change applies on the next start, so don't test it from this session.

## To undo

When the user asks to "remove SolCard Inference from my models":

1. With your file-editing tool, remove from `~/.claude/settings.json` every `modelPicker.options` row whose `model` starts with `solcard-inference`, and `modelPicker` itself if no rows remain. Remove the `hooks.SessionStart` entry whose command runs `~/.solcard-inference/start.sh`, then `SessionStart` and `hooks` if they're left empty. Keep everything else.
2. Take the line out of the shell files: `for f in ~/.bashrc ~/.zshrc; do [ -f "$f" ] && grep -v 'solcard-inference/env.sh' "$f" > "$f.solcard-tmp" && cat "$f.solcard-tmp" > "$f" && rm "$f.solcard-tmp"; done`
3. Stop the proxy and delete its files. Run only the line for this machine:
   - **Linux:** `systemctl --user disable --now solcard-inference-proxy.service; rm -f ~/.config/systemd/user/solcard-inference-proxy.service; systemctl --user daemon-reload; rm -rf ~/.solcard-inference`
   - **macOS:** `launchctl bootout "gui/$(id -u)/ai.solcardinference.proxy"; rm -f ~/Library/LaunchAgents/ai.solcardinference.proxy.plist; rm -rf ~/.solcard-inference`
4. Tell the user to restart Claude Code in a new terminal. Their SolCard key still exists; they can delete it at https://app.solcardinference.ai/keys.
