macOS menubar app with an in-process OpenAI-compatible HTTP proxy so Zed can use a SuperGrok subscription (OAuth) or an xAI API key.
Workspace version 0.1.0. First release is macOS only.
Quit stops the proxy. The Python connector often keeps serving after you quit the menu bar app (LaunchAgent). This app runs the proxy in the same process. Quit cancels the listener and frees the port.
If
http://127.0.0.1:8787is already taken, Stop the other SuperGrok app or unload the leftover agent — do not install a new one:launchctl bootout gui/$UID/com.supergrok.zed.connector
The first-release product path works end to end: build or assemble the unsigned .app, sign in (API key or browser OAuth), talk to Zed, and quit to unbind the port.
| Area | State |
|---|---|
| Menubar + Settings (GPUI + tray) | Ready |
In-process proxy (127.0.0.1:8787) |
Ready — Quit unbinds the port |
Zed Agent (POST /v1/chat/completions) |
Ready (stream + non-stream) |
| Zed Inline Assistant | Ready if you use the snippet’s inline_assistant_use_streaming_tools: false |
Auth (api_key and oauth) |
Ready — Settings → Account |
Drop-in ~/.config/supergrok-zed/ |
Ready — same paths as the Python connector |
Unsigned local .app (LSUIElement) |
Ready — not notarized |
Zed Edit Prediction (POST /v1/completions) |
Experimental — Zed now POSTs; xAI 410 (retired Live Search) and 400 (too many stop strings) are handled. Ghost-text quality can still be empty when reasoning eats max_output_tokens. |
Not in this release: LaunchAgent / quit-keeps-proxy, Windows or Linux tray, Developer ID / notarized DMG, a standalone serve CLI.
- macOS 14+
- Full Xcode (not Command Line Tools only). Point the active developer dir at the app:
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
- Metal toolchain (required to compile GPUI):
xcodebuild -downloadComponent MetalToolchain
- Rust stable — this repo pins
[toolchain] channel = "stable"inrust-toolchain.toml.
From the workspace root:
cargo build -p supergrok-zed
cargo run -p supergrok-zedUse cargo run -p supergrok-zed --release for a faster binary.
On non-macOS hosts the package is a stub that exits 1 so workspace CI can still compile. That is expected.
cargo run applies NSApplicationActivationPolicyAccessory after launch. A brief Dock flash on that path is normal (dev-only). Look at the menu bar, not the Dock.
An unsigned local .app is optional. From the workspace root:
./crates/supergrok-zed/packaging/assemble-app.sh
open "target/release/bundle/SuperGrok for Zed.app"There is no Dock icon. Control the app from the menu bar. Close Settings and the process stays alive; Quit still stops the proxy and frees the port.
This artifact is unsigned and not notarized. A Developer ID / notarized DMG is out of scope. If macOS quarantines a downloaded copy, right-click → Open (Gatekeeper). Agent apps can be hard to find in Force Quit — use the tray Quit item.
cargo run and the .app may not share Keychain items (different code identity). ~/.config/supergrok-zed/env is the portable store.
Finder launch has no TTY. Use Console.app, or:
log stream --predicate 'process == "supergrok-zed"'Debug with cargo run when you want stdout. Adding the app to Login Items is optional and user-owned; Quit still stops the proxy.
Do not run the Python connector (or its LaunchAgent) at the same time — they both want port 8787.
-
No window opens. Click the SuperGrok tray icon in the menu bar.
-
Settings… → Account — paste an API key or Sign in with xAI (browser + loopback
127.0.0.1:56121). -
The proxy auto-starts when the active auth mode already has a secret. Otherwise use Start Proxy.
-
Confirm:
curl -s http://127.0.0.1:8787/healthz # {"status":"ok"} -
Close Settings — the process stays running.
-
Quit from the tray. The same curl must fail (connection refused). That is how you know the proxy died with the app.
| Item | Role |
|---|---|
| Status line | Connected (127.0.0.1:8787), Stopped, Starting…, or a short error |
| Start / Stop | Listen / unbind (Start needs an active-mode secret) |
| Settings… | GPUI window — General, Account, Edit Prediction |
| Copy base URL | http://127.0.0.1:8787/v1 |
| Copy Zed settings snippet | Single JSON object (Agent + Inline + Edit Prediction) |
| Quit | Cancel proxy, unbind, exit |
The tray menu stays open while the proxy is Connected (status updates in place).
Save writes ~/.config/supergrok-zed/config.toml and the env file (0600), then hot-swaps or rebinds the in-process proxy.
| Section | Fields |
|---|---|
| General | Host, port, log level |
| Account | api_key vs oauth, paste API key, Sign in / Sign out with xAI |
| Edit Prediction | Enable local POST /v1/completions; backend responses (default) or chat |
Process environment variables still win on Start / relaunch, not on an in-session Settings Save.
Reuse ~/.config/supergrok-zed/ as-is (config.toml + env). This binary does not bump model ids in an existing file.
- Stop the Python app / unload
com.supergrok.zed.connectorso port8787is free. - Start this binary. It loads the
envfile itself (the Python LaunchAgent used tosourceit). Process environment variables still override after load. - You do not need to
export XAI_API_KEYfor the menubar app. - In Zed
settings.json, deletelanguage_models.openai.api_url(and any SuperGrok models underopenai). If that key stays, all native OpenAI traffic keeps going to localhost. - The Agent default provider is
supergrok, not"openai". Authenticate that provider with dummySUPERGROK_API_KEY=local(or the Zed provider UI). - Alias
supergrokstill follows yourconfig.tomlaliases (Python files often targetgrok-4.5). Pickgrok-4.6in Zed to pass that id through without editing the file.
Secrets belong in ~/.config/supergrok-zed/env (mode 0600), never in config.toml.
Exactly one mode is active: auth_mode = "api_key" or "oauth" (invalid values become api_key).
| Mode | Bearer | Where it lives | Billing |
|---|---|---|---|
api_key |
XAI_API_KEY |
Settings → Account, or env |
Pay-per-token console.x.ai |
oauth |
XAI_ACCESS_TOKEN |
Settings → Sign in with xAI… | SuperGrok / X Premium subscription |
- The unused mode’s secrets are ignored, not deleted.
- Subscription OAuth and developer API keys are separate billing. A SuperGrok login does not authorize console API usage, and vice versa.
- Some subscription tiers return HTTP 403 on OAuth-backed API calls. Switch
auth_modetoapi_keyand set a console key. Do not clear OAuth tokens on 403 — they may still refresh. - Sign out clears OAuth only. The API key is kept. Mode stays
oauthuntil you change it. - Client
Authorizationheaders are ignored. The server injects the Bearer for the active mode.
Local loopback only. No connector auth on the socket.
| Method | Path | Notes |
|---|---|---|
GET |
/healthz |
{"status":"ok"} — no auth, no upstream |
GET |
/v1/models |
Local catalog (aliases + known models) |
POST |
/v1/chat/completions |
Proxy to {upstream}/chat/completions; stream + non-stream |
POST |
/v1/completions |
Experimental FIM → xAI Responses (default) or chat; 404 when completions_enabled is false |
The connector never calls xAI’s legacy /completions.
Merge one JSON object into the existing settings.json root. Zed loads only the first top-level object — never paste a second {...} after the file’s closing brace.
Prefer tray Copy Zed settings snippet (matches the object below). Authenticate the named provider with dummy SUPERGROK_API_KEY=local (or the Zed provider UI). Select supergrok or grok-4.6, not gpt-*.
{
"language_models": {
"openai_compatible": {
"supergrok": {
"api_url": "http://127.0.0.1:8787/v1",
"available_models": [
{
"name": "supergrok",
"display_name": "SuperGrok (local connector)",
"max_tokens": 500000,
"capabilities": {
"tools": true,
"images": true,
"parallel_tool_calls": true,
"prompt_cache_key": true,
"chat_completions": true,
"interleaved_reasoning": true,
"max_tokens_parameter": false
}
},
{
"name": "grok-4.6",
"display_name": "Grok 4.6",
"max_tokens": 500000,
"capabilities": {
"tools": true,
"images": true,
"parallel_tool_calls": true,
"prompt_cache_key": true,
"chat_completions": true,
"interleaved_reasoning": true,
"max_tokens_parameter": false
}
}
]
}
}
},
"agent": {
"default_model": {
"provider": "supergrok",
"model": "supergrok"
},
"inline_assistant_model": {
"provider": "supergrok",
"model": "supergrok"
},
"inline_assistant_use_streaming_tools": false
},
"edit_predictions": {
"provider": "open_ai_compatible_api",
"open_ai_compatible_api": {
"api_url": "http://127.0.0.1:8787/v1/completions",
"model": "supergrok",
"prompt_format": "star_coder",
"max_output_tokens": 512
}
}
}This is a named openai_compatible provider. It does not hijack native OpenAI. Keep Zed’s native x_ai provider for official console models in parallel.
Grok 4.6 streams reasoning_content before assistant text. Zed’s default Inline Assistant streaming-tools path (rewrite_section) treats that Thinking event as unexpected and shows nothing; it also ignores plain delta.content. Agent chat handles Thinking correctly.
inline_assistant_modelalone is not enough.capabilities.tools: falsedoes not disable the tools path (Zed still reports streaming tools).- The snippet sets
agent.inline_assistant_use_streaming_tools: falseso Inline Assist applies replacement text. This flag is agent-wide in Zed (not per provider). If you later use another provider that needs tool-driven inline, set it back totrue. - If you already pasted an older snippet, re-copy from the tray and merge the new
agentkeys into the same root object.
POST /v1/completions is not xAI legacy /completions. Default backend is {upstream}/responses with store: false. Search stays off by omitting search_parameters (do not send Agent Tools / web_search). Set completions_backend = "chat" (or SUPERGROK_ZED_COMPLETIONS_BACKEND=chat) to map through chat instead — that is Responses vs chat mapping, not a Live Search workaround.
Set completions_enabled = false (or SUPERGROK_ZED_COMPLETIONS_ENABLED=0) to disable the local completions path (OpenAI-shaped 404). Chat and /healthz stay up. Process env wins on Start / relaunch, not on an in-session Settings Save. Copy snippet (and tray copy) uses edit_predictions.provider: "none" when disabled — still one JSON object.
Zed prompt_format: "infer" only works for a closed model-name list (zeta2, qwen, starcoder, codestral, …). Names like supergrok and grok-4.6 are not on that list: Zed assigns no Edit Prediction provider and sends no HTTP. The snippet therefore sets prompt_format: "star_coder" and keeps model: "supergrok". If you already pasted an older snippet with "infer", re-copy from the tray and merge into the same root object.
There is no failover between Responses and chat. Same-URL retries only.
Reasoning tokens count against max_output_tokens. Zed’s typical 256–512 limit can be consumed by reasoning and return an empty insertion. This connector does not raise that limit.
~/.config/supergrok-zed/config.toml (defaults):
host = "127.0.0.1"
port = 8787
default_model = "grok-4.6"
upstream = "https://api.x.ai/v1"
request_timeout_s = 600
connect_timeout_s = 10
max_retries = 2
log_level = "info"
log_prompts = false
auth_mode = "api_key" # or "oauth"
completions_backend = "responses" # or "chat"
completions_enabled = true # false → local POST /v1/completions is 404
[aliases]
supergrok = "grok-4.6"
grok = "grok-4.6"Env overrides (same names as the Python connector; process env wins after the env file is loaded):
| Variable | Purpose |
|---|---|
SUPERGROK_ZED_HOST |
Bind host |
SUPERGROK_ZED_PORT |
Bind port |
SUPERGROK_ZED_DEFAULT_MODEL |
Default model id |
SUPERGROK_ZED_UPSTREAM |
xAI base URL |
SUPERGROK_ZED_LOG_LEVEL |
Tracing filter |
SUPERGROK_ZED_CONFIG |
Path to config.toml |
SUPERGROK_ZED_ENV |
Path to secrets file |
SUPERGROK_ZED_ALLOW_REMOTE |
Allow 0.0.0.0 / :: (1 / true / yes / on) |
SUPERGROK_ZED_AUTH_MODE |
api_key or oauth |
SUPERGROK_ZED_COMPLETIONS_BACKEND |
responses or chat |
SUPERGROK_ZED_COMPLETIONS_ENABLED |
Gate local POST /v1/completions (1/true/yes/on; falsey 0/false/no/off) |
Never put secrets in config.toml. Write them to ~/.config/supergrok-zed/env (created/updated as mode 0600):
XAI_API_KEY=your_key_here- Default bind is
127.0.0.1only.0.0.0.0/::is refused unlessSUPERGROK_ZED_ALLOW_REMOTEis truthy. - There is no connector auth on the local socket. Anyone who can reach the bind address can use your upstream credential.
log_promptsdefaults to false. API keys, access/refresh tokens, andAuthorizationheaders are never logged.
| Symptom | What to try |
|---|---|
| Port 8787 in use | Stop the other SuperGrok app, or launchctl bootout gui/$UID/com.supergrok.zed.connector. Then Start again. |
| Sign-in fails / port 56121 in use | Another SuperGrok instance is holding the OAuth loopback. Quit it. |
| 401 from chat/completions | Active mode has no server secret. Set an API key or Sign in with xAI. /healthz never requires auth. |
| 403 on OAuth | Billing mismatch. Switch to api_key + console key. Do not wipe OAuth tokens. |
| Zed ignores SuperGrok | You pasted a second top-level JSON object. Merge into the existing root. |
Zed still on gpt-* |
Select model supergrok. A default of gpt-5.4 will not use local aliases. |
| EP never hits the connector / status bar still Zeta or Copilot | Connector never logs POST /v1/completions. Merge explicit prompt_format: "star_coder" (not "infer" next to model: "supergrok"). Confirm edit_predictions.provider is open_ai_compatible_api, not leftover "zed" / "none". Do not paste a second top-level JSON object. |
Edit Prediction status=410 / Live Search deprecated |
Connector used to send search_parameters.mode=off; xAI retired that field. This build omits it. Do not flip completions_backend as a Live Search workaround — chat mapping is not a 410 escape hatch. |
Edit Prediction status=400 / more than 8 stop strings |
Zed star_coder often sends ~14 stop values. xAI chat allows 8. This build forwards the first 8 on the chat backend and still trims the rest locally. Default responses does not send stop. |
| Empty Edit Prediction | Reasoning ate max_output_tokens (256–512). Experimental; no backend failover. |
- A LaunchAgent, a standalone
serveCLI, or a Python/uv installer - A connector process that outlives the menubar app
- Windows or Linux (first release is macOS only)
- A notarized / Developer ID DMG
Contributors and agents: start at AGENTS.md. Research notes live in RESEARCH.md.
MIT. Copyright © 2026 Andreas Gerlach (appelgriebsch).
Inspired by andypduk/supergrok-zed (MIT). This repository is a separate Rust + GPUI implementation; Andy Dennis is not the maintainer of this binary.