Multi-subscription AI chat for VS Code: Claude, GPT, and Gemini at one table, in one shared-context conversation — authenticated through your existing consumer subscriptions (Claude Max, ChatGPT Plus/Pro, Google account) via the CLIProxyAPI sidecar. No API keys, ever.
⚠️ Using subscription accounts outside their official apps may violate the providers' Terms of Service and can lead to rate limiting or account suspension. You proceed at your own discretion.
SquareCode keeps one canonical transcript per thread. Whenever any participant speaks, it receives the entire labeled transcript as context — so every model is always on the same page. Address a participant with @claude, everyone with @all, or just type and let the "speaking to" selector (or round-robin mode) decide.
The models are reached through CLIProxyAPI, a localhost proxy that wraps subscription OAuth logins and exposes an OpenAI-compatible API.
npm install
npm run compile # typecheck + lint + build both bundles
npm test # vitest unit + integration suitesPress F5 in VS Code to launch the Extension Development Host, then open the SquareCode icon in the activity bar.
npm run mock-server # OpenAI-compatible mock on http://127.0.0.1:9999In the dev host's settings (JSON):
Send @all hello — you should see two sequential streamed replies, a green status pill, and thread persistence across window reloads.
- Download
CLIProxyAPI_7.2.66_windows_amd64.zipandchecksums.txtfrom the v7.2.66 release. - Verify:
(Get-FileHash .\CLIProxyAPI_7.2.66_windows_amd64.zip -Algorithm SHA256).Hashand compare with the matching line inchecksums.txt. - Extract to e.g.
C:\Tools\cliproxyapiand createconfig.yamlthere:host: "127.0.0.1" port: 8317 api-keys: [] remote-management: secret-key: ""
- Log in with your subscription (browser opens):
.\cli-proxy-api.exe -config .\config.yaml -claude-login(also:-codex-loginfor ChatGPT,-antigravity-loginfor Google,-kimi-loginfor Moonshot,-xai-loginfor Grok — or use the in-panel Accounts button) - Run it:
.\cli-proxy-api.exe -config .\config.yaml - Check what model ids your account exposes:
Invoke-RestMethod http://127.0.0.1:8317/v1/models | ConvertTo-Json -Depth 4 - Set
"squarecode.sidecar.mode": "external", keep the defaultexternalUrl(http://127.0.0.1:8317), and point your participants'modelfields at real ids from step 6.
With "squarecode.sidecar.mode": "managed" (the default), SquareCode downloads the pinned CLIProxyAPI release itself (after asking), verifies its SHA256, generates a locked-down localhost config, and supervises the process — restart with SquareCode: Sidecar: Restart, log in with SquareCode: Sidecar: Log In to Provider….
- Model picker: header dropdown (per "To:" target) + SquareCode: Change Participant Model command, both fed by the sidecar's live
/v1/models. Changes write back tosquarecode.participants. - Intelligence picker: reasoning effort with provider-native levels (
none / auto / low / medium / high / xhigh / max) — a per-participant default (effortin settings) plus a sticky per-send override next to the composer ("Set default" saves it to the seat). - Live status: each streaming bubble shows "Thinking… Ns" → "Streaming — N tokens" → a permanent
N tokens · Nsfooter; multi-responder turns get a queue strip ("Alpha ✓ · Beta thinking · Gamma queued"). - Todo widgets: participants are taught to emit
```todoblocks with- [ ]/- [x]lines; they render as live checklists with a progress count. - Thinking panel: reasoning text streams into a collapsible per-bubble panel when the sidecar emits it. Note: CLIProxyAPI ≤ 7.2.66 accepts
reasoning_effortand runs thinking (visible in token counts and the thinking timer) but does not yet forward the reasoning text through the OpenAI-compatible stream — the panel appears automatically once a release with thereasoning_contenttranslator ships.
- Accounts flyout (⚿ in the header): connect any subscription CLIProxyAPI v7.2.66 supports — Claude, OpenAI/ChatGPT (browser or device-code), Google (via Antigravity), Moonshot/Kimi, xAI/Grok. Connected status is inferred purely from the live model list (token files are never read). Sign-ins run in a VS Code terminal.
- Bottom-panel mount: SquareCode appears as a tab in the Panel row (Terminal/Output area) in addition to the sidebar and the editor-area command — all mounts share one live conversation.
- Pixel wordmark: the header now carries a Press Start 2P "SQUARECODE" wordmark (OFL-licensed font bundled locally — no network fetch).
- The flame: Bonfire is armed via the 🔥 toggle next to the effort picker — it flickers on hover, burns steadily while armed, stays armed across sends until you turn it off, and deliberately disarms on target/thread switches and panel remounts so it can never silently burn quota. (Static glow under
prefers-reduced-motion.)
The top entry in the effort picker. What it really is: Bonfire burns several requests' worth of your subscription quota on a single send to get the best answer the model can produce. SquareCode plays coordinator: a planner call decomposes your request into 2–4 subtasks, parallel subagent calls each work one subtask at max thinking effort, an adversarial critique call hunts for errors and gaps, and a synthesis call streams the final reply into the thread.
What it is not: agent workflows. SquareCode participants have no tools — the "subagents" are text-only chat completions that can reason about what's in the conversation, but cannot read files, run commands, or act on anything. It is parallel thinking about your prompt, not parallel doing. Expect roughly 4–7× the tokens of a normal send (each internal call carries the transcript); the aggregate cost shows on the bubble's token footer. All intermediate work streams into the collapsible panel and is discarded — only the final reply is persisted. Bonfire is per-send only; it cannot be a participant default.
| Setting | Default | Purpose |
|---|---|---|
squarecode.sidecar.mode |
managed |
Who runs CLIProxyAPI: SquareCode or you |
squarecode.sidecar.port |
8317 |
Managed sidecar port |
squarecode.sidecar.binaryPath |
"" |
Use your own binary in managed mode |
squarecode.sidecar.externalUrl |
http://127.0.0.1:8317 |
Your proxy's URL in external mode |
squarecode.participants |
[] |
The seats at the table (id, displayName, color, model, systemPrompt, enabled) |
squarecode.router.defaultMode |
manual |
Who answers unmentioned messages: the selector, or round-robin |
squarecode.context.autoIncludeActiveFile |
false |
Attach the active file to every message |
squarecode.prompt.softLimitChars |
150000 |
Prompt budget before oldest messages are omitted |
- M1 — the loop: mock server → green pill; send → progressively streamed markdown reply; Stop → "(stopped)" partial; reload window → thread restored; kill proxy → red pill with reason on hover.
- M2 — the table: two participants on one backend;
@all→ two sequential replies, the second aware of the first;@-mention order respected; unknown@fooignored; round-robin alternates; Retry re-runs failures; Delete tombstones (excluded from later prompts). - M3 — managed sidecar: fresh install → consent prompt → download → green pill with no manual proxy; kill the process in Task Manager → auto-restart; kill it 4× fast → red pill + working Restart; login flow end-to-end; a foreign proxy on 8317 → "attached, not managed"; close the dev host → no orphaned
cli-proxy-api.exe. - M4 — polish:
@popup fully keyboard-operable (Enter accepts, never sends); selection → chip → collapsed context block; ToS banner exactly once per install; prompt-size hint under the composer; corrupt thread file on disk → quarantined*.corrupt-*.json, activation survives.
npm run package # produces squarecode-<version>.vsix
code --install-extension squarecode-0.1.0.vsixSee CLAUDE.md in the repository — the canonical product rules (transcript schema and invariants, prompt-assembly role mapping, router rules, sidecar lifecycle, webview protocol).