Skip to content
This repository was archived by the owner on Sep 27, 2026. It is now read-only.
appelgriebschPublic archive

About

A small local proxy to use your SuperGrok subscription in Zed.dev

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

41 Commits

Folders and files

Repository files navigation

SuperGrok for Zed (Rust)

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:8787 is 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

Status

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.

Prerequisites

  • 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" in rust-toolchain.toml.

Build and run

From the workspace root:

cargo build -p supergrok-zed
cargo run -p supergrok-zed

Use 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.

Packaged app

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.

First run

  1. No window opens. Click the SuperGrok tray icon in the menu bar.

  2. Settings… → Account — paste an API key or Sign in with xAI (browser + loopback 127.0.0.1:56121).

  3. The proxy auto-starts when the active auth mode already has a secret. Otherwise use Start Proxy.

  4. Confirm:

    curl -s http://127.0.0.1:8787/healthz
    # {"status":"ok"}
  5. Close Settings — the process stays running.

  6. Quit from the tray. The same curl must fail (connection refused). That is how you know the proxy died with the app.

Tray

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).

Settings

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.

Migrate from the Python connector

Reuse ~/.config/supergrok-zed/ as-is (config.toml + env). This binary does not bump model ids in an existing file.

  1. Stop the Python app / unload com.supergrok.zed.connector so port 8787 is free.
  2. Start this binary. It loads the env file itself (the Python LaunchAgent used to source it). Process environment variables still override after load.
  3. You do not need to export XAI_API_KEY for the menubar app.
  4. In Zed settings.json, delete language_models.openai.api_url (and any SuperGrok models under openai). If that key stays, all native OpenAI traffic keeps going to localhost.
  5. The Agent default provider is supergrok, not "openai". Authenticate that provider with dummy SUPERGROK_API_KEY=local (or the Zed provider UI).
  6. Alias supergrok still follows your config.toml aliases (Python files often target grok-4.5). Pick grok-4.6 in Zed to pass that id through without editing the file.

Secrets belong in ~/.config/supergrok-zed/env (mode 0600), never in config.toml.

Auth

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_mode to api_key and 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 oauth until you change it.
  • Client Authorization headers are ignored. The server injects the Bearer for the active mode.

HTTP API

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.

Zed

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.

Inline Assistant vs Agent

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_model alone is not enough.
  • capabilities.tools: false does not disable the tools path (Zed still reports streaming tools).
  • The snippet sets agent.inline_assistant_use_streaming_tools: false so 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 to true.
  • If you already pasted an older snippet, re-copy from the tray and merge the new agent keys into the same root object.

Edit Prediction (experimental)

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

~/.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

Security

  • Default bind is 127.0.0.1 only. 0.0.0.0 / :: is refused unless SUPERGROK_ZED_ALLOW_REMOTE is truthy.
  • There is no connector auth on the local socket. Anyone who can reach the bind address can use your upstream credential.
  • log_prompts defaults to false. API keys, access/refresh tokens, and Authorization headers are never logged.

Troubleshooting

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.

What this is not

  • A LaunchAgent, a standalone serve CLI, 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.

License

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.

About

A small local proxy to use your SuperGrok subscription in Zed.dev

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages