Releases: satindergrewal/Spock
Release list
v0.3.0
What's new in v0.3.0
Added
- Vision policy for text-only backends (
text_only = trueon oauth/api_key backends +[vision]section) — text-only upstreams (vLLM DSV4-Flash etc.) hard-400 on image content, and clients re-send the full transcript, so one screenshot poisons every later request in the session. Spock now rewrites image content before the request leaves:mode = "strip"(default) replaces images with an omission note;mode = "describe"captions each screenshot via an OpenAI-compatible VL sidecar (llama-server + mmproj) and inlines the caption as text. Any sidecar failure degrades to strip — a request never dies here. Covers/v1/messages(incl. anthropic passthrough and KV sessions) and the verbatim/v1/chat/completionsingress. Captions cached in memory only (sha256 of image + prompt); no per-request image limit — one failed sidecar call strips the rest of that request (bounded stall), a healthy sidecar captions every image. Retroactively un-sticks poisoned sessions: the next request goes out clean. glm-5.3 name-matcher flatten unchanged as a safety net. POST /v1/responsessearch shim — grok-buildweb_searchposts OpenAI Responses ({base}/responses+ hostedweb_searchtool). Search-only: run[web_search](Brave/Serper/SearXNG/DDG) and return a completed Responses object withoutput_text+url_citation. No tool / search disabled / empty query → 400. Not a general Responses proxy (no chat/completions fallback).- macOS Settings Catalog effort column — auto / 1 / 0 next to context; Save & Apply writes
supports_reasoning_effortso Grok Build/modelTab shows effort on non-heuristic rows (Qwen, local GGUF) - llama-server KV sessions (
kv_sessions = trueon an api_key backend) — Claude Code traffic parks a named master via native/completion, childrenPOST /forkwithparent_session_id, leave viaPOST /close_session./v1/chat/completionsis never the session path. Missing routes or unknown session error the request (no silent cold prefill). Inherit proof: HTTPcache_n/prompt_n. Headers:x-spock-session,x-spock-parent-session,x-spock-close-session.cache_controlon the shared prefix names the master. - Generalized OAuth providers — registry-driven
spock login|logout <provider>/spock providers(xai, kimi, qwen); status + menus follow the table - Backend types:
oauth/api_key/anthropic(Settings labels: OAuth / API Key / Anthropic) - Kimi Code OAuth (
provider = "kimi",https://api.kimi.com/coding/v1, KimiCLI UA + X-Msh headers) - Qwen OAuth (optional) —
provider = "qwen"chat.qwen.ai device flow + PKCE S256; uses tokenresource_urlwhen present (qwen-code path) - Qwen Cloud (qwencloud.com) documented as
type = "api_key"ondashscope-intl…/compatible-mode/v1+DASHSCOPE_API_KEY(Token Plan / Max Preview) - Token files:
~/.config/spock/oauth-<provider>.json(imports legacy grok-test / kimi-cli / qwen-code paths once; logout clears them)
Changed
- Breaking: bare
spock loginremoved — usespock login xai(orkimi/qwen) - Proxy never opens a browser mid-request; refresh is single-flight per provider
- Long streaming generations: idle read/write timeouts (1h) instead of total 600s request caps; stream clients skip server-tools buffer path; backend map lock dropped before upstream I/O
- macOS app: Local Network + Bonjour keys so LAN backends work from Spock.app
- Product framing: multi-backend Anthropic Messages proxy (not Grok-only)
Fixed
- Mid-conversation
role:"system"reminders 400 on template-strict upstreams: Claude Code delivers some system-reminders (e.g. the Agent-tool types list) asrole:"system"messages insidemessages. Qwen3.5+ jinja chat templates (SGLang / vLLM / llama.cpp) hard-400 withSystem message must be at the beginning.— LAN Qwen looked dead (GPU idle) while every request died at template validation. Generic (OpenAI-compat) backends and the llama-server KV path now fold non-leading system messages into user turns wrapped in<system-reminder>tags (the client's own idiom); xAI / Kimi keep passthrough. - z.ai GLM 5.3 text-only content: Claude Code screenshots become OpenAI
image_urlparts; GLM-5.3 400smessages.content.type is invalid, allowed values: ['text']. Flatten images to a text note forglm-5.3*only — vision backends unchanged. - Accepted sockets inherit
O_NONBLOCKon Darwin: listen socket is nonblocking so the accept loop can poll shutdown. macOS/accept()copies that flag onto the client fd;read_exactthen returnsWouldBlock(os error 35) as soon as the kernel buffer is empty. Claude Code reportsECONNRESET; Grok Build reportsreqwest error stream: error sending request. Force blocking + idle timeouts on every accepted socket./v1/chat/completionsnow logsrouteand emits a stream error event instead of dying silent. - Catalog
/v1/models: non-empty catalog is served from local entries only. Live backend/modelsprobes no longer block Grok's ~5s catalog fetch (empty/modelpicker,unknownfooter). - Advisor protocol: run the nested review; never leak
advisoras clienttool_use(No such tool available: advisor). Flatten leftoverserver_tool_use/advisor_tool_resultto text on the OpenAI-compat path (xAI 400). VSCodium 2.1.226 webview cannot render those block types (Unsupported content type: server_tool_useas a chat line) — emit labeled text instead. Strip<|eos|>. Log advisor start/end/duration. - WebSearch on stream: Claude Code nested
web_search_20250305calls now run Spock server-tool emulation (was skipped whenstream:true); emit realserver_tool_use+web_search_tool_resultblocks; SSE keepalives during long rounds - Login… from the menu bar runs as a direct child process (no Terminal/AppleScript stall)
- Menu + CLI surface already-logged-in OAuth state clearly
- Slow LAN (llama-server) streams no longer die at ~10 minutes while the backend still generates
- Mid-SSE llama.cpp tool-call diff aborts (
Invalid diff: now finding less tool calls) labeled as upstream llama-server, not Spock - Streamed OpenAI tool_calls merge by
index(Qwen/Token Plan): emptyidarg chunks no longer open extra tool_use blocks — fixes Claude Code Bash getting empty/broken commands on Fable→Qwen - Route
backend:modelclient ids to that backend when it exists (stop falling through to profile default / xAI) - Docs: Qwen Cloud Coding Plan (
coding-intl…,sk-sp-…) vs Token Plan (token-plan.ap-southeast-1…, separate key) —qwen3.8-max-previewis Token Plan only
Install (macOS App — Apple Silicon)
- Download
Spock-0.3.0-darwin-arm64.zip - Unzip → drag Spock.app to Applications
- First open: right-click → Open if Gatekeeper blocks (ad-hoc signed)
- Menu bar → Login xAI… or paste an API key in Settings
Claude Code: set ANTHROPIC_BASE_URL=http://127.0.0.1:8048
CLI
| Platform | Asset |
|---|---|
| macOS arm64 | spock-0.3.0-darwin-arm64.tar.gz |
| macOS x64 | spock-0.3.0-darwin-x64.tar.gz |
| Linux x64 | spock-0.3.0-linux-x64.tar.gz |
| Linux arm64 | spock-0.3.0-linux-arm64.tar.gz |
| Windows x64 | spock-0.3.0-windows-x64.zip |
tar -xzf spock-0.3.0-darwin-arm64.tar.gz
sudo mv spock-0.3.0-darwin-arm64/spock /usr/local/bin/
spock serveConfig: ~/.config/spock/config.toml
OAuth: ~/.config/grok-test/auth.json · or API key / XAI_TOKEN
SHA-256: see checksums.txt.
Full Changelog: v0.2.0...v0.3.0
v0.2.0
Local multi-backend Anthropic Messages proxy for Claude Code — xAI Grok, Ollama / llama-server, OpenAI-compat (OpenRouter, …), Anthropic passthrough, advisor + web_search emulation.
Install (macOS App — Apple Silicon)
- Download
Spock-0.2.0-darwin-arm64.zip - Unzip → drag Spock.app to Applications
- First open: right-click → Open if Gatekeeper blocks (ad-hoc signed)
- Menu bar → Settings… — add backends / profiles; Login xAI… only if you use Grok OAuth
Claude Code: set ANTHROPIC_BASE_URL=http://127.0.0.1:8048
Also: Spock-0.2.0-darwin-x64.zip for Intel Macs.
CLI
| Platform | Asset |
|---|---|
| macOS arm64 | spock-0.2.0-darwin-arm64.tar.gz |
| macOS x64 | spock-0.2.0-darwin-x64.tar.gz |
| Linux x64 | spock-0.2.0-linux-x64.tar.gz |
| Linux arm64 | spock-0.2.0-linux-arm64.tar.gz |
| Windows x64 | spock-0.2.0-windows-x64.zip |
tar -xzf spock-0.2.0-darwin-arm64.tar.gz
sudo mv spock-0.2.0-darwin-arm64/spock /usr/local/bin/
spock serveConfig: ~/.config/spock/config.toml
xAI OAuth (optional): ~/.config/grok-test/auth.json · or API key / XAI_TOKEN
SHA-256: see checksums.txt.
Full Changelog: v0.1.0...v0.2.0
v0.1.0
Install (macOS App — Apple Silicon)
- Download
Spock-0.1.0-darwin-arm64.zip - Unzip → drag Spock.app to Applications
- First open: right-click → Open if Gatekeeper blocks (ad-hoc signed)
- Menu bar → Login xAI… or paste an API key in Settings
Claude Code: set ANTHROPIC_BASE_URL=http://127.0.0.1:8048
CLI
| Platform | Asset |
|---|---|
| macOS arm64 | spock-0.1.0-darwin-arm64.tar.gz |
| macOS x64 | spock-0.1.0-darwin-x64.tar.gz |
| Linux x64 | spock-0.1.0-linux-x64.tar.gz |
| Linux arm64 | spock-0.1.0-linux-arm64.tar.gz |
| Windows x64 | spock-0.1.0-windows-x64.zip |
tar -xzf spock-0.1.0-darwin-arm64.tar.gz
sudo mv spock-0.1.0-darwin-arm64/spock /usr/local/bin/
spock serveConfig: ~/.config/spock/config.toml
OAuth: ~/.config/grok-test/auth.json · or API key / XAI_TOKEN
SHA-256: see checksums.txt.
Full Changelog: https://github.com/satindergrewal/Spock/commits/v0.1.0