中文 | English
Adapted from raine/claude-code-proxy. This project is a Cursor-first local proxy for Claude Code and Grok Build (grok / grok-build).
Run Cursor models (Fable 5) from Claude Code or grok-build — stably.
Claude Code ──Anthropic /v1/messages──► claude-cursor-proxy (:18765)
grok-build ──Responses / Messages ──► │
├── Cursor (Fable 5) ← primary
├── Codex ← additional
├── Kimi
└── Grok
Quick start · Models · Sand mode · Features · Config · MCP troubleshooting · Limitations
Claude Code speaks Anthropic (/v1/messages). grok-build speaks OpenAI Responses (/v1/responses). Cursor uses its own Agent protocol. They do not talk to each other directly.
This tool runs a local one-way proxy (default 127.0.0.1:18765):
- Claude Code or grok-build send their usual requests to the proxy
- The proxy translates them for Cursor and forwards upstream
- It streams the matching SSE back — Anthropic
pingkeep-alive for Claude Code, Responses events for grok-build
Primary upstream: Cursor (Fable 5). Additional backends in the same process: Codex, Kimi, Grok.
Not affiliated with Anthropic, Cursor, OpenAI, Moonshot, or xAI.
| Stable sessions | HTTP/2 BiDi upstream + Anthropic ping SSE keep-alive downstream |
| Fable 5 | Set ANTHROPIC_MODEL=claude-fable-5[1m] (and the same for ANTHROPIC_SMALL_FAST_MODEL) |
| Usage / ctx | Cursor turn usage mapped onto Anthropic usage for status lines and compaction |
| Tools | Cursor exec / native tools remapped into Claude Code and grok-build tool loops (best-effort) |
| Simple install | Checksummed binaries; macOS ad-hoc codesign; config under ~/.config/claude-cursor-proxy |
Honest scope: best-effort compatibility — not a full Cursor IDE mirror. See Limitations.
curl -fsSL https://raw.githubusercontent.com/YeautyYE/claude-cursor-proxy/main/install.sh | bashmacOS / Linux. Windows: download the .zip from Releases (or use WSL).
Other install options
| Method | Command |
|---|---|
| Pin version | CLAUDE_CURSOR_PROXY_VERSION=v0.1.115 curl -fsSL …/install.sh | bash |
| Custom dir | CLAUDE_CURSOR_PROXY_INSTALL_DIR=/opt/bin bash install.sh |
| From source | cargo install --git https://github.com/YeautyYE/claude-cursor-proxy --locked |
| Fork / mirror | GITHUB_REPO=owner/repo curl -fsSL https://raw.githubusercontent.com/owner/repo/main/install.sh | bash |
claude-cursor-proxy cursor auth login
claude-cursor-proxy serve # 127.0.0.1:18765 + monitor TUI
claude-cursor-proxy serve --no-monitor # logs only
claude-cursor-proxy serve --port 11435 # custom portRun claude-cursor-proxy cursor auth login in another terminal while serve
is running. Credentials are re-read from the store on every request, so:
- new requests use the new account immediately;
- in-flight runs keep the token they captured at start and finish on the previous login — nothing is interrupted;
- existing sessions start a fresh Cursor conversation on their next turn (the client resends its history automatically).
cursor auth status shows the active account. Note: if
CCP_CURSOR_AUTH_TOKEN/CURSOR_AUTH_TOKEN is set in the serve process's
environment, the env token shadows the store and a login hot swap will not
take effect until you unset it.
Use login when you want the newly authenticated account to become active.
Use add when you want to keep the current account active and append another
login to the local account pool:
claude-cursor-proxy cursor auth add --label work
claude-cursor-proxy cursor auth list
claude-cursor-proxy cursor auth use ACCOUNT_ID
claude-cursor-proxy cursor auth usage # every saved account
claude-cursor-proxy cursor auth usage ACCOUNT_ID # one account
claude-cursor-proxy cursor auth usage --json # machine-readableACCOUNT_ID may be the id printed by list, an unambiguous email, or a label.
The pool is stored in cursor/accounts.json; the selected credential remains
mirrored to the existing cursor/auth.json so older installations continue to
work. In the monitor TUI, press a to open the account panel, Enter to
switch, u to fetch the selected account, and U to fetch every account in
parallel. Each account has its own refresh worker, so moving to another row
does not cancel the account that was just refreshed. Successful snapshots are
cached under the state directory and shown again on the next TUI open; the
Updated column (or the selected-row detail on narrow terminals) shows the
last dashboard fetch time. Press r to refresh the account list and all usage.
Press d on a selected account, then y/Enter to confirm deletion
(n/Esc cancels). Removing the active account immediately activates the next
available account. Adding, switching, or removing accounts does not require
restarting serve.
To reserve a saved account for particular models, press m from the main TUI
or the account panel. Use j/k to select a model and Enter/Space to choose
a saved account or automatic; press x to clear an assignment or
a to enter a catalog id that is not listed yet. Changes apply to new requests
immediately without changing the active account. Model-bound live runs,
conversation checkpoints, KV state, and tool continuations are partitioned by
account, so two models can use different accounts concurrently in one serve
process. The TUI stores the stable account id; labels and emails remain useful
selectors for headless configuration.
export ANTHROPIC_BASE_URL=http://127.0.0.1:18765
export ANTHROPIC_AUTH_TOKEN=unused
export ANTHROPIC_MODEL=claude-fable-5[1m]
export ANTHROPIC_SMALL_FAST_MODEL=claude-fable-5[1m]
export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
export CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK=1
claudeSame keys work under "env" in ~/.claude/settings.json.
Always set ANTHROPIC_SMALL_FAST_MODEL to a full model id (same as ANTHROPIC_MODEL is fine). Otherwise Claude Code’s background small-model calls return HTTP 400.
Codex / Kimi / Grok
claude-cursor-proxy codex auth login
ANTHROPIC_BASE_URL=http://127.0.0.1:18765 ANTHROPIC_AUTH_TOKEN=unused \
ANTHROPIC_MODEL=gpt-5.6-sol[1m] ANTHROPIC_SMALL_FAST_MODEL=gpt-5.6-luna[1m] \
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK=1 \
claude
claude-cursor-proxy kimi auth login # or: grok auth logingrok-build 1.0.13 has two endpoint layers. Startup account settings and the
model catalog use the global GROK_CLI_CHAT_PROXY_BASE_URL setting (or
[endpoints].cli_chat_proxy_base_url); a [model.*].base_url only controls
inference after startup. Point the global endpoint at this proxy as well as
each model block below. The environment variable is convenient for a one-shot
run; the TOML setting is persistent.
1. Log in (once) and start the proxy
claude-cursor-proxy grok auth login # required for grok-4.5 / grok-4.6 chat
claude-cursor-proxy cursor auth login # only if you also route Fable / Composer
claude-cursor-proxy serve # 127.0.0.1:187652. Edit ~/.grok/config.toml — set the global startup endpoint and
override the official ids so Fast + effort menus stay enabled. Fast is
reasoning.effort = "low".
# ~/.grok/config.toml
[endpoints]
# Grok startup settings/model-catalog requests (required for local proxy):
cli_chat_proxy_base_url = "http://127.0.0.1:18765/v1"
# Optional image/video tools (also a global endpoint):
xai_api_base_url = "http://127.0.0.1:18765/v1"
[auth]
# Do not let an expired grok.com OIDC token block local-proxy startup.
# The proxy uses its own saved upstream credential for these requests.
preferred_method = "api_key"
[model.grok-4.6]
base_url = "http://127.0.0.1:18765/v1"
api_key = "unused"
[model.grok-4.5]
base_url = "http://127.0.0.1:18765/v1"
api_key = "unused"
# Cursor catalog via grok-build (official OpenAI Responses, not Claude Messages)
[model.cursor-grok]
model = "cursor-grok-4.6-xhigh-fast"
base_url = "http://127.0.0.1:18765/v1"
api_backend = "responses"
api_key = "unused"
# Optional: Claude Code-style Anthropic Messages (not the grok-build default)
[model.via-ccp]
model = "claude-fable-5[1m]"
base_url = "http://127.0.0.1:18765/v1"
api_backend = "messages"
context_window = 1000000
api_key = "unused"
supports_reasoning_effort = true
reasoning_effort = "high"
3. Run grok-build
grok --model grok-4.6
# or: grok --model grok-4.5
# or: grok --model cursor-grok
# or: grok --model via-ccpFor a temporary shell/session, the equivalent global override is:
GROK_CLI_CHAT_PROXY_BASE_URL=http://127.0.0.1:18765/v1 \
grok --model grok-4.6Inbound api_key is accepted (Authorization: Bearer … or x-api-key; unused, other placeholders, and JWT-looking session tokens are treated as empty) and is not used as a user/tenant id. Grok /v1/responses passthrough forwards conversation, compaction (x-compaction-at, x-compactions-remaining), doom-loop, and a charset-limited x-grok-model-override — never Authorization, Cookie, or x-grok-user-id.
GET /v1/models advertises model, context_window, api_backend=responses (grok-build's official OpenAI Responses backend), supports_reasoning_effort, and reasoning_efforts (grok-4.6 includes xhigh / high / medium / low). A custom [model.*] block that omits api_backend defaults to Chat Completions in grok-build; set api_backend = "responses". This proxy does not implement /v1/chat/completions. /v1/messages remains for Claude Code.
Media routes (/v1/images/*, /v1/videos/*) proxy to https://api.x.ai/v1 (override with CCP_GROK_MEDIA_BASE_URL). A real client key is forwarded; placeholders and grok-build session JWTs fall back to the stored Grok OAuth token.
Set ANTHROPIC_MODEL and ANTHROPIC_SMALL_FAST_MODEL to full model ids. Recommended Cursor default: claude-fable-5[1m].
Other backends use their own full ids (for example gpt-5.6-sol[1m], kimi-for-coding, grok-composer-2.5-fast). Unknown ids return 400.
# Built-in registry
claude-cursor-proxy models
claude-cursor-proxy models --full
# While serve is running — Anthropic-compatible list
# (merges Cursor GetUsableModels when logged in + registry)
curl -s http://127.0.0.1:18765/v1/models | jq '.data[].id'Sand is a separate Cursor request surface selected per model. For a model
that matches the Sand policy, the proxy sends Cursor's
x-cursor-client-type: sand; other Cursor models keep the normal cli (or
your configured CCP_CURSOR_CLIENT_TYPE) identity. Mixed routing happens in
the same claude-cursor-proxy serve process; a second Sand binary is not
needed.
grok-bot is the name of Cursor's server-side Bot/Sand product and entitlement;
it is not a local process that must be started before the proxy. On a
first-use account, complete Cursor's one-time Bot onboarding in a browser:
https://cursor.com/bot/onboarding?product=grok-bot. After the account has
the entitlement, keep only claude-cursor-proxy serve running. If the account
was just onboarded, run cursor auth login/cursor auth usage once to refresh
the stored session and quota snapshot. A response such as Sand traffic is not supported on this endpoint means the selected route rejects Sand traffic. The
current proxy keeps plain text and Fable's text-tool/history bridge on
InferenceService/Stream; native Sand tool catalogs prefer the strict
InferenceService/RunInference handshake and fall back to Stream on that
exact route rejection (direct-stream: ready in cursor sand-status confirms
the base Sand route).
The policy applies only to requests resolved to the Cursor provider; Codex,
Kimi, and native Grok routes keep their normal providers by default. There is
one intentional Grok exception: an explicit cursor.modelAccounts rule for a
grok-* name opts that name into Cursor's account-backed Grok catalog. This
lets the same public id be used either for the native Grok provider or for a
Cursor account, but the two paths have different logins and quota meters.
Sand selection and account selection are independent. For example,
gemini-3.1-pro can be marked [sand] with s and assigned to a specific
Cursor account with m; both settings are applied to the same request.
Cursor exposes two independent allowance lanes. The account selected by
modelAccounts only chooses which account is used; it does not switch a
request between these lanes:
| TUI marker | Cursor surface | Dashboard meter | Meaning |
|---|---|---|---|
[cli] |
AgentService / x-cursor-client-type: cli |
CLI/API (apiPercentUsed, plus Auto/Total) |
Normal Cursor CLI requests |
[sand] |
Desktop InferenceService / x-cursor-client-type: sand |
Sand/Grok Bot (usagePercent) |
Sand requests, including Cursor Grok |
The percentages are used percentages: 100% means that lane is
exhausted. A low Sand/Bot value does not replenish an exhausted CLI/API lane,
and a full CLI/API meter does not mean Sand is unavailable. The account panel
and the m model-account editor show both meters; the selected model's lane is
shown first. Use u for one account or U for all accounts to refresh a
stale snapshot, then check the Updated timestamp.
The proxy never silently changes the quota lane. For an account-scoped Sand
policy/allowance error, it tries the other saved, non-cooled accounts in the
same lane, with a per-request hard ceiling of 16 swaps; an explicit
model-account binding keeps failover within that binding. Change the model's
[cli]/[sand] selection or its account binding in the TUI when you need a
different lane or a deterministic account.
grok-4.6 is a name shared by two providers:
- With no Cursor model-account rule,
grok-4.6uses the native Grok provider and thegrok auth logincredential. Cursor CLI/Sand quotas do not apply. - A
cursor.modelAccountsrule forgrok-4.6(or an explicitcursor-grok-4.6-*catalog id) selects the Cursor provider and the mapped Cursor account.cursor auth login/cursor auth addmanage that account. - To spend the Sand/Grok Bot meter, mark the exact Cursor model as
[sand]in the TUI.highandxhighcatalog ids are separate rows and can be mapped to different accounts; do not rely on a broad rule when the tiers have different balances.
Recommended TUI flow for a Cursor Grok 4.6 request:
-
Press
s, pressaif needed, and add/selectcursor-grok-4.6-xhigh-fast; toggle it to[sand]. -
Press
m, select the same model row, choose the account with the desired Sand/Bot balance, and pressEnter. -
Point grok-build (or Claude Code) at that exact id. For grok-build:
[model.cursor-grok-sand] model = "cursor-grok-4.6-xhigh-fast" base_url = "http://127.0.0.1:18765/v1" api_backend = "responses" api_key = "unused"
grok --model cursor-grok-sand
If the Events/Requests pane shows cursor-grok-4.6-xhigh-fast [cli], the
request is spending CLI/API quota even when the mapped account still has
Sand/Bot capacity; toggle that exact row to [sand]. If it shows [sand] and
the Sand meter is available, inspect the selected account name/email and the
Updated time before retrying. A native grok --model grok-4.6 profile remains
on the native Grok provider unless it is explicitly account-bound to Cursor.
For a definitive mapping check, inspect the structured proxy log while sending
one request. For a future diagnostic launch, enable the flags before serve
and use a spare port; leave an existing serve process untouched:
CCP_LOG_STDERR=1 CCP_LOG_VERBOSE=1 claude-cursor-proxy serve --no-monitor --port 18766Point the diagnostic client at http://127.0.0.1:18766; otherwise keep using
the existing port and inspect its proxy.log.
The cursor_account_selected record includes accountBinding; both it and
policy_rate_limit_breaker_open include the truncated accountId, resolved
model, clientType, quotaLane, and cached apiPercent/botPercent values.
No bearer token is included. Compare those fields with the model badge and the
account row's Updated time. A mismatch identifies a routing/configuration
issue; matching fields confirm which account and lane were attempted, while
Cursor may still reject that lane for a policy or capacity decision.
SandClientMode and SandStreamToolkit are version-locked Cursor Desktop
bundle patchers. This proxy does not install, modify, or require a patched
Cursor.app: it routes each selected request through its own Sand H2 path.
The optional Desktop-bundle section in sand-status is informational only.
Recommended: configure Sand from the monitor TUI. Keep one
serveprocess running and use the shortcuts below; this avoids hand-editing configuration files and makes the active request type visible immediately.
On the first interactive start, the TUI opens a Default Transport chooser.
Select CLI / API or Bot / Sand with the arrows or j/k, then press
Enter to save. This is the fallback for Cursor models without an explicit
[sand] selection; per-model Sand selections still take priority. The saved
choice is reused on later starts. Press t at any time to reopen the chooser
and switch the default. If CCP_CURSOR_CLIENT_TYPE is set, it remains the
authoritative environment override and the TUI leaves it unchanged.
| Key | Action |
|---|---|
s |
Open Sand Models and select the model list |
j / k |
Move through models |
Space / Enter |
Toggle the selected model between [sand] and [cli] |
a |
Add a model id manually (for example claude-fable-5) |
u |
Open the account-usage view |
a (main view) |
Open the Cursor account panel |
m (main view) |
Assign Cursor models to saved accounts |
t |
Choose the default CLI / API or Bot / Sand lane |
Esc / s |
Close the Sand editor |
claude-cursor-proxy cursor auth login
claude-cursor-proxy serve # keep the monitor TUI openIn the monitor TUI, press s to open Sand Models. Use j/k to select a
model, Space or Enter to toggle it, and a to enter an exact Cursor
catalog id such as claude-fable-5. From the model list, press u to inspect
account usage. The list is marked [sand] or [cli]; changes apply to new
requests and are written atomically to config.json. The TUI requires a
terminal; serve --no-monitor keeps the proxy running without it.
Fable has no built-in Sand exception. It follows the same explicit model
policy as every other Cursor model: select claude-fable-5 (or a catalog
variant) in Sand Models to mark it [sand], or leave it unselected to use
the configured default identity. An empty policy is valid and no model is
added implicitly.
For a read-only terminal diagnostic, run:
claude-cursor-proxy cursor sand-status
claude-cursor-proxy cursor sand-status --jsonThis reports the effective model policy, Sand client version, H2 transport,
proxy route markers, account names, and usage-cache timestamps. Its Desktop
bundle inspection is explicitly marked optional and requiredForProxy: false;
the command does not open a Cursor request or consume model quota. JSON output
contains no access or refresh tokens.
Cursor model cells in the Sessions, Active requests, Recent requests, and
Events panes carry the same [sand]/[cli] badge, so the selected request
surface is visible without opening the editor. Fable aliases are resolved
before matching: a rule for claude-fable-5-thinking-max also covers the
usual claude-fable-5[1m], fable[1m], and cursor: forms.
This TUI flow is the recommended way to manage Sand routing. You do not need
to edit a file or launch another binary; the running serve process picks up
the saved policy for the next request. Environment variables and
config.json are fallback interfaces for automation, not the normal setup
path.
After enabling a model with s, point Claude Code at that model:
export ANTHROPIC_BASE_URL=http://127.0.0.1:18765
export ANTHROPIC_AUTH_TOKEN=unused
export ANTHROPIC_MODEL="claude-fable-5"
export ANTHROPIC_SMALL_FAST_MODEL="claude-fable-5"
claudeFor a temporary shell/session or automation, CCP_CURSOR_SAND_MODELS can
override the TUI policy:
export CCP_CURSOR_SAND_MODELS="claude-fable-5"To add an exact Cursor catalog id that is not in the current list, press a
inside Sand Models and enter it directly; for example,
claude-fable-5.
CCP_CURSOR_SAND_MODELS is a comma-separated list and supports * and ?.
Model matching is case-insensitive and normalizes [1m] plus
cursor:/cursor-agent:/cursor-plan:/cursor-ask: prefixes, so a rule for
claude-fable-5 also covers cursor:claude-fable-5[1m]. An environment value
always overrides cursor.sandModels in config.json; unset it to edit the
file from the TUI. Leave CCP_CURSOR_CLIENT_TYPE at its default cli when you
want mixed routing; setting it to sand makes unmatched models use Sand too.
Model-specific rules are authoritative and have no hidden Fable exception;
account selection and quota failover remain independent.
The built-in Cursor catalog is only an offline/startup fallback. With a Cursor
login, the proxy fetches GetUsableModels at startup and refreshes it when
GET /v1/models is requested. It also probes Cursor's
aiserver.v1.AiService/AvailableModels catalog when available; that response
contains canonical family ids, aliases, and effort variants needed to map a
CLI slug such as gemini-3.6-flash-high to the Sand family id
gemini-3.6-flash. Catalog snapshots are scoped by account and request
identity (cli versus sand) and expire after a short TTL, so one account or
lane cannot leak model entitlements into another. The returned account catalog
is merged into the TUI and model list. You can still add an exact id with a
or set it in the environment, but the signed-in Cursor account must expose that
model upstream. The active view changes immediately on an account switch, and
an in-flight response from the previous account is discarded. Fresh snapshots
for other saved accounts remain separately keyed for fast model/account
switching; logout clears the active live snapshot.
The live catalog cache is process-local (it never stores credentials) and its
TTL is 5 minutes. Within that window repeated /v1/models calls and
concurrent warm-up requests reuse one snapshot (one request per account and
cli/sand identity); a refreshed access JWT keeps the same account key.
A proxy restart starts with the built-in fallback and refreshes the live
catalog in the background; it does not load a catalog file from disk. This
keeps model entitlements scoped to the account/session that supplied them.
The monitor polls Cursor's read-only dashboard endpoints and shows the signed-in
account, plan, Auto/API percentages, on-demand dollars, dashboard cost/event
totals, and the Sand/Grok Bot period meter when the account provides it. Press
u for the multi-line usage view, including the Sand period and recent usage
events. cursor auth status shows the active login. On macOS, the monitor can
fall back to Cursor Desktop's read-only state.vscdb; missing dashboard fields
are omitted rather than invented. In headless serve --no-monitor, a lightweight
poller requests only the Sand meter once per minute so an exhausted Sand turn
can still be reported as HTTP 429; usage display remains a TUI feature. The
full dashboard poll interval is 60 seconds; the in-memory Sand/API evidence
used for classifying payload-less turns expires after 180 seconds when
dashboard requests temporarily fail.
Successful per-account dashboard snapshots are cached at
~/.local/state/claude-cursor-proxy/cursor/account-usage.json on macOS/Linux
(or the platform state directory). The cache contains usage data and fetch
timestamps only, never access or refresh tokens, and is rebuilt automatically
when it is missing or corrupt; an older snapshot remains visible until a
successful refresh replaces it.
If a worker panics or exceeds its watchdog, the last successful snapshot stays
visible and the row leaves its stuck refreshing state. Once the detached
request exits, u can retry it; a late network result is accepted only for the
account credentials that produced it.
claude-cursor-proxy cursor auth status- Anthropic surface:
POST /v1/messages,count_tokens,/healthz,/v1/models - grok-build surface:
POST /v1/responses,POST /v1/images/generations,POST /v1/images/edits,POST /v1/videos/generations,GET /v1/videos/{id} - Cursor Agent Connect (BiDi
Run); optional HTTP/1 viaCCP_CURSOR_HTTP1=1 - SSE keep-alive (
ping) so quiet thinking does not look stalled - Model routing by
ANTHROPIC_MODEL - Auth stored by the proxy; Cursor can fall back to Cursor Agent Keychain /
auth.json - Monitor TUI when stdout is a TTY (
demofor a simulated UI)
For interactive routing and usage inspection, prefer the monitor TUI: s
selects Sand models, m assigns models to Cursor accounts, a opens account
management, and u opens account usage. The file and environment settings
below are primarily for headless or automated deployments.
Precedence: env > config.json > defaults.
| Platform | Path |
|---|---|
| macOS / Linux | ~/.config/claude-cursor-proxy/config.json |
| Windows | %APPDATA%\claude-cursor-proxy\config.json |
Override with CCP_CONFIG_DIR. Env prefix stays CCP_* (unchanged from earlier builds). Provider auth files under previous paths (~/.config/claude-cursor-bridge/, ~/.config/claude-code-proxy/) are still read as a migration fallback.
| Variable | Default | Purpose |
|---|---|---|
PORT |
18765 |
Listen port |
CCP_BIND_ADDRESS |
127.0.0.1 |
Bind address |
CCP_ADVERTISED_MODELS |
unset | Optional comma-separated allowlist for GET /v1/models (useful for managed desktop model pickers) |
CCP_CURSOR_AUTH_TOKEN |
unset | Cursor bearer override |
CCP_CURSOR_BASE_URL |
https://api2.cursor.sh |
Cursor API base |
CCP_CURSOR_SAND_BASE_URL |
value of CCP_CURSOR_BASE_URL |
Optional base URL for Sand InferenceService/Stream / RunInference |
CCP_CURSOR_SAND_CLIENT_VERSION |
0.30.0 |
Sand/Grok Bot API identity version; override only for a gateway that requires it |
CCP_CURSOR_SAND_STRICT_H2 |
0 |
Force strict H2 prior-knowledge for Sand; normal TLS ALPN is recommended for HTTPS proxies |
CCP_CURSOR_CLIENT_TYPE |
cli |
Default x-cursor-client-type value; the TUI t chooser persists the same setting in cursor.clientType |
CCP_CURSOR_SAND_MODELS |
unset | Comma-separated model selectors routed with x-cursor-client-type: sand; supports * and ? |
CCP_CURSOR_SAND_OPEN_CONCURRENCY |
512 |
Maximum simultaneous Sand InferenceService cold opens (1–512); the logical request queue remains 512 |
CCP_CURSOR_SAND_ACCOUNT_OPEN_CONCURRENCY |
512 |
Maximum simultaneous Sand cold opens per account/model lane (1–512); this is a handshake limit, not a hidden low concurrency default |
CCP_CURSOR_SAND_OPEN_INITIAL_INFLIGHT |
32 |
Initial global cold-open in-flight window (1–512); successful opens ramp toward the 512 hard ceiling |
CCP_CURSOR_SAND_OPEN_INITIAL_RATE |
32 |
Initial cold-open launch rate per second (1–512); this is a handshake ramp, not the logical request limit |
CCP_CURSOR_SAND_ACCOUNT_OPEN_INITIAL_INFLIGHT |
32 |
Initial per-account/model cold-open window (1–512); isolated per route and adaptive after outcomes |
CCP_CURSOR_SAND_ACCOUNT_OPEN_INITIAL_RATE |
32 |
Initial per-account/model cold-open launch rate per second (1–512) |
CCP_CURSOR_SAND_OPEN_RATE |
512 |
Cold-open launch-rate ceiling; transient failures do not reduce the process-wide window (1–512) |
CCP_CURSOR_SAND_OPEN_QUEUE_SECS |
3 |
Sand admission queue slice (1–120s); saturated requests stay queued and retry the slice without issuing unbounded upstream opens |
CCP_CURSOR_SAND_OPEN_TIMEOUT_SECS |
90 |
Per-attempt Sand HTTP open timeout (10–180s) |
CCP_CURSOR_SAND_OPEN_TOTAL_SECS |
180 |
Total budget for one Sand open/retry episode (20–900s) |
CCP_CURSOR_SAND_OPEN_RETRIES |
unset (TOTAL_ATTEMPTS - 1) |
Maximum retries inside one Sand open episode (0–8); an explicit value can lower the hard attempt cap |
CCP_CURSOR_SAND_TOTAL_ATTEMPTS |
3 |
Hard transport-attempt budget for one open episode (1–8); the whole logical turn is additionally bounded by CCP_CURSOR_SAND_LOGICAL_ATTEMPTS |
CCP_CURSOR_SAND_LOGICAL_ATTEMPTS |
8 |
Total Sand transport opens allowed across the initial open and all pre-output replays for one logical turn (1–32) |
CCP_CURSOR_SAND_ACCOUNT_FAILOVER_ATTEMPTS |
16 |
Maximum fresh account handoffs for one logical Sand turn (1–16); independent from transport retries |
CCP_CURSOR_SAND_OPERATION_ENTRIES |
2048 |
Maximum in-process logical Sand operation records; excess requests receive bounded backpressure |
CCP_CURSOR_SAND_OPERATION_SUBSCRIBERS |
512 |
Maximum attached HTTP retries for one logical operation; matches the documented fan-out |
CCP_CURSOR_SAND_OPERATION_REPLAY_EVENTS / CCP_CURSOR_SAND_OPERATION_REPLAY_BYTES |
16384 / 16MiB |
Bounded replay history used by duplicate requests; oversized histories stay single-owner |
CCP_CURSOR_SAND_RETRY_BUDGET_SECS |
600 |
Shared logical budget across the initial Sand open and pre-output stream replays (60–3600s); queue time is included here, while each admitted open gets its own transport budget |
CCP_CURSOR_SAND_BREAKER_THRESHOLD |
3 |
Consecutive transient Sand open failures before the account/model circuit cools down (1–16) |
CCP_CURSOR_SAND_BREAKER_COOLDOWN_SECS |
15 |
Sand account/model circuit cooldown (1–300s) |
CCP_CURSOR_MODEL_ACCOUNTS |
unset | JSON object or model=account list assigning Cursor model selectors to account ids, unique labels, or emails; supports * and ? |
CCP_CURSOR_STATE_DB |
Cursor Desktop state path on macOS | Optional read-only state.vscdb path used by the TUI usage fallback |
CCP_CURSOR_HAIKU_MODEL |
claude-haiku-4-5 |
Cursor catalog id used for Anthropic haiku aliases and desktop small-model probes |
CCP_CURSOR_CATALOG_REQUEST_TIMEOUT_SECS |
4 |
Timeout for the optional AvailableModels metadata probe (capped at 30 seconds) |
CCP_CURSOR_CLI_KEYCHAIN_FALLBACK |
on | Disable with 0 / false |
CCP_CURSOR_EMBED_SYSTEM |
off | Forward Anthropic system into Cursor user text (can trigger Fable injection loops) |
CCP_CURSOR_FORCE_TOOLS_IN_PROMPT |
off | Dump all tool schemas (large); BiDi already keeps Claude-local tools (Workflow/Skill/…) |
CCP_CURSOR_LIVE_CONCURRENCY |
1024 |
Fair cap for bulk (cursor-grok-*) generation starts (1–8192) |
CCP_CURSOR_LIVE_RUNS |
4096 |
Process-wide cap for live requests holding a Run slot (1–16384); generation-start capacity is controlled separately by CCP_CURSOR_LIVE_CONCURRENCY |
CCP_CURSOR_LIVE_INTERACTIVE_RESERVE |
128 |
Protected start capacity for non-Grok models (Gemini/Claude/… subagents); interactive starts may also borrow idle bulk slots, but bulk never borrows the reserve (0–1024) |
CCP_CURSOR_LIVE_QUEUE_SECS |
30 |
Maximum local admission wait before retryable HTTP 503 (1–300s) |
CCP_CURSOR_LIVE_ATTACH_WAIT_MS |
15000 |
Same-operation attach handoff wait before local busy is returned (500–60000ms) |
CCP_CURSOR_LIVE_RESUME_ATTACH_WAIT_MS |
4000 |
Pre-response same-operation attach wait (500–5000ms); kept below the Claude Code stream watchdog |
CCP_CURSOR_LIVE_CONFLICT_WAIT_MS |
180000 |
Wait for a different operation to observe the current session Run advance (500–600000ms) |
CCP_CURSOR_LIVE_RESUME_WAIT_MS |
5000 |
Pre-response tool-result handoff wait; kept below the client stream watchdog (500–5000ms) |
CCP_CURSOR_LIVE_NESTED_WAIT_MS |
1500 |
Pre-response nested-agent handoff wait (500–5000ms) |
CCP_CURSOR_RESOURCE_RETRIES |
6 |
Same-request retries for transient Cursor ERROR_RESOURCE_EXHAUSTED responses (1–12); billing/quota/capacity policy 429s are never hidden-retried |
CCP_CURSOR_POLICY_429_COOLDOWN_SECS |
30 |
Local cooldown after an account/model/Sand-or-CLI policy 429; fresh requests on that exact route fail fast with HTTP 429 + Retry-After (5–600s) |
CCP_CURSOR_POLICY_429_PROBE_WINDOW_MS |
30000 |
CLI/API cold account/model/route single-flight window: useful output releases the wave immediately; a quiet expiry admits only one additional probe (25–120000ms) |
CCP_CURSOR_SAND_POLICY_429_PROBE_WINDOW_MS |
5000 |
Sand/Bot cold account/model single-flight window; later quota evidence still opens the account breaker (25–120000ms) |
CCP_CURSOR_STEP_FAILURE_RETRIES |
4 |
Same-request retries for pre-output Cursor Failed to run step, exceeded max retries failures (1–8); post-output failures are forwarded |
CCP_CURSOR_LIVE_RESUME_RESERVE |
64 |
Additional capacity reserved for paused Runs that need to submit tool results (0–512) |
CCP_CURSOR_OPERATION_LEDGER |
off | Opt-in durable operation ledger (crash-safe replay refusal). Stays off by default until completion is gated on downstream delivery, so dropped responses cannot permanently refuse client retries |
CCP_CURSOR_LIVE_TIMEOUT_SECS |
1800 |
Active model-generation budget for each live segment (max 3600s; paused while downstream tools run) |
CCP_CURSOR_TOOL_TTL_SECS |
same as live timeout | Maximum wait after a tool batch reaches the downstream client; an admitted result is allowed to finish dispatch |
CCP_CURSOR_HEARTBEAT_PROGRESS_SECS |
1200 |
Maximum heartbeat-only thinking period without model progress |
CCP_CURSOR_GEMINI_FLASH_PROGRESS_SECS |
180 |
Gemini Flash heartbeat-only progress deadline; a hollow pre-output run is rotated and retried inside the same client request instead of appearing stuck |
CCP_CURSOR_H2_SHARDS |
16 |
Stable H2 client pools used to isolate concurrent conversations (1–64) |
CCP_CURSOR_LIVE_RECOVERY_OPENS |
16 |
Process-wide cap for simultaneous ResumeAction replacement opens (1–128) |
CCP_ANTHROPIC_SSE_PING_SECS |
5 |
SSE heartbeat interval (message_delta + ping; keep below Claude Code's 10s stream watchdog) |
CCP_CURSOR_NO_PROXY |
off | Skip HTTP(S)_PROXY for Cursor API (1 / true) |
CCP_LOG_STDERR / CCP_LOG_VERBOSE / CCP_TRAFFIC_LOG |
unset | Debug |
The two Sand open limits cover the HTTP/2 handshake and request headers; those permits are released as soon as the upstream stream is established. The logical request queue and hard ceiling remain 512. The default cold-open window starts at 32 and grows after successful headers, so a fresh Grok route does not receive a synchronized 512-way handshake burst. Operators can tune the global and per-account/model initial windows and rates when a private gateway needs a different ramp. There is deliberately no second process-wide lifetime semaphore for accepted model streams: long generations and tool pauses must not turn the documented 512-way fan-out into a local 504 queue. A saturated open lane is fairly admitted with a pair-wise gate (a waiter never holds an account permit while waiting for a global one), and the shared sharded H2 client pool avoids a new TCP/TLS client per request. Unbound requests that remain behind a slow account lane can rotate on the same account until the bounded logical retry budget is exhausted; explicit model-account bindings stay pinned, while quota/authentication errors still use the account-pool failover path. These controls shape handshake pressure and observability without changing the client's logical concurrency; accepted streams are released by the normal driver on End, transport error, or downstream cancellation.
These are Claude Code knobs (not proxy config). Useful when /deep-research or ToolSearch misbehaves through a custom ANTHROPIC_BASE_URL:
| Variable / setting | Purpose |
|---|---|
enableWorkflows: true (settings) |
Force Workflows on if your plan defaults them off |
ENABLE_TOOL_SEARCH=true |
Re-enable ToolSearch when BASE_URL is not api.anthropic.com |
_CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URL=1 |
Treat proxy BASE_URL as first-party for some gates (use only if you know you need it) |
Rules / skills: Claude Code injects CLAUDE.md and skill text into /v1/messages locally (often as user <system-reminder>). The proxy forwards those messages; it does not strip them. Top-level Anthropic system stays omitted by default (opt in with CCP_CURSOR_EMBED_SYSTEM=1).
Verify /deep-research: transcript should show a Workflow tool_use (name: deep-research), not only Bash curl/mkdir.
{
"bindAddress": "127.0.0.1",
"port": 18765,
"cursor": {
"sandModels": ["claude-fable-5"],
"modelAccounts": {
"claude-fable-5": "work",
"gemini-3.1-pro": "ACCOUNT_ID"
}
},
"log": { "stderr": false, "verbose": false }
}This is the shape written by the TUI; manual editing is mainly useful for
automation. Account values may be the id printed by cursor auth list, a
unique label, or a unique email. Model selectors are case-insensitive and may
contain * and ?; an exact model rule wins over a wildcard rule. For an
environment-only deployment, the equivalent account policy is:
export CCP_CURSOR_MODEL_ACCOUNTS='{"claude-fable-5":"work","gemini-*":"ACCOUNT_ID"}'See Sand mode for the complete routing, TUI, model discovery, and usage guide.
If Claude Code repeatedly prints
MCP server 'plugin:lobster-channel:lobster-channel' not connected, the
message is produced by Claude Code's local hook dispatcher when its Lobster
client is missing or stale. It happens before an HTTP request reaches this
proxy, so proxy stream retries do not repair the local MCP registry.
One confirmed cause is Lobster 1.23.0's local lifecycle: Claude Code can
start one plugin process per session while the processes share a bridge
binding. When a newer process takes over, the bridge closes the older one with
code 4405 (session superseded), and that runtime calls process.exit(1).
The older Claude session then keeps a disconnected MCP registry entry and can
print the error on every hook. Competing pairing processes can similarly cause
4407 handshake takeovers. This is a local Lobster/session-lifecycle problem,
not a Cursor inference-stream retry failure.
Use this order:
-
Keep the existing
serveprocess. Use the monitor TUI first: presssto inspect or toggle Sand models anduto inspect account usage. A second Sand binary is not needed. -
Inspect the selected project:
claude-cursor-proxy mcp-doctor --cwd "$PWD" claude-cursor-proxy mcp-doctor --cwd "$PWD" --json
The doctor scans installed
dist/server.jsfiles for the exit-prone 4405 branch, reports explicit 4405/4407 log events, and warns when multiple Lobster processes can compete for the shared binding. If it reports an exit-prone runtime, update Lobster to a build that keeps a superseded process dormant instead of terminating the stdio MCP child. -
If the report lists Lobster under
disabledMcpServers, runclaude-cursor-proxy mcp-doctor --cwd "$PWD" --repair. The repair makes a timestamped backup and removes only Lobster entries. Start a new Claude Code session after the repair. -
For an existing session, try
/mcp reconnect plugin:lobster-channel:lobster-channel. If the session still reportsnot connectedafter a 4405 exit, start a new session after updating Lobster; reconnecting the registry cannot revive a child process that already exited. This does not require restarting the proxy. -
Batch commands such as
claude --bare --tools "" -p ...should use a dedicated Claude config directory, so global Lobster hooks are not loaded into a process with no matching MCP client:BATCH_CONFIG="$(mktemp -d)" CLAUDE_CONFIG_DIR="$BATCH_CONFIG" claude --bare --tools "" -p "$PROMPT"
Put only the settings needed by the batch in that directory; do not copy the global plugin/hooks tree. The doctor follows Claude Code's path rules: default
~/.claude.json, or$CLAUDE_CONFIG_DIR/.claude.jsonwhen the variable is non-empty. A legacy.config.jsonis used only when the canonical file is absent.
- Not official. Provider ToS and account risk are yours.
- No client auth on the proxy. Loopback by default; non-loopback only behind a firewall or authenticating reverse proxy.
- Rate limits follow the upstream account.
- Parity is best-effort. Text, tools, thinking, and streaming work for supported paths; some edge cases are approximated or omitted.
- Not a full Cursor IDE. Workspace/tool callbacks beyond Claude Code / grok-build tool loops are incomplete.
- Linux prebuilts are glibc. Alpine/musl: build from source.
| Symptom | Fix |
|---|---|
macOS Killed: 9 |
codesign --force -s - "$(command -v claude-cursor-proxy)" |
| Auth / 401 | claude-cursor-proxy cursor auth login |
| Background 400 | Set ANTHROPIC_SMALL_FAST_MODEL to a known full model id |
| Duplicated tools | CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK=1 |
Claude Code prints Edit unavailable / switches to StrReplace, or an edit call loops |
Update to ≥0.1.83 and restart serve. Claude Code 2.1.193's text_editor_20250728 / str_replace_based_edit_tool pair is preserved end-to-end; Cursor PiEdit replacements are normalized and returned with the matching native result. |
/deep-research uses Bash/curl only |
Update proxy (≥ Workflow passthrough); confirm Workflow in transcript; set enableWorkflows: true if needed |
| Hung SSE | Check ~/.local/state/claude-cursor-proxy/proxy.log; try CCP_LOG_STDERR=1 CCP_TRAFFIC_LOG=1 serve --no-monitor |
Image attachment immediately fails with 502 Image not found [internal] |
Update to ≥0.1.83 and restart serve. The proxy keeps the original inline bytes, rotates the selected-image id once, and retries on a fresh Cursor conversation; a persistent upstream error is then surfaced instead of opening an unbounded retry loop. |
grok-build returns 413 Cursor KV blob store limit exceeded (blobs=4097 / about 64 MiB) |
Update to ≥0.1.84 and restart serve. The proxy rotates a near-limit Cursor conversation before the next turn; an upstream 413 receives one bounded fresh-conversation retry with the complete Anthropic history and refreshed image ids. No manual /compact or new chat is needed. |
Gemini/Fable Sand returns ERROR_PRO_USER_RATE_LIMIT_EXCEEDED while the same model works as CLI |
Sand and CLI are separate Cursor request identities and quota buckets. In the TUI press s, select the model, and toggle it to [cli]; the proxy keeps Sand 429s visible and does not silently spend the CLI/API allowance. |
grok-build/Claude Code gets HTTP 429 You're out of usage for grok-4.6 or cursor-grok-* while the mapped account still has Sand/Bot balance |
Check the request badge first. [cli] uses the account's CLI/API meter; [sand] uses Sand/Grok Bot. A model→account binding selects a credential but does not change the lane. For Cursor Grok, add the exact cursor-grok-4.6-* id in Sand Models, toggle [sand], then bind that same row with m; refresh with u/U and verify Updated. Bare grok-4.6 remains the native Grok provider unless explicitly account-bound to Cursor. |
grok-build Server error (500) - Something went wrong on our side on unpaid invoice or unsupported country/region |
Update to ≥0.1.47 and restart serve. Cursor billing is HTTP 429 with the invoice text; geo/policy blocks are HTTP 403 with the country/region text. |
grok-build Server error (500) after Cursor live open timed out / duplicate Cursor runs |
Update to ≥0.1.57 and restart serve. Response-less live opens fail closed as HTTP 409; local open-slot saturation is jittered HTTP 503. |
Sand bursts show 503 Sand open admission queue timed out |
Update to the current release and restart serve. Admission applies bounded backpressure: saturated requests wait for a real open slot instead of flooding Cursor with untracked opens. Genuine upstream capacity errors still use bounded retries and Retry-After. |
Claude Code unexpected internal error then live open timed out after 10s (often gemini-3.6-flash-high) |
Update to ≥0.1.58 and restart serve. HTTP/1 ResumeAction uses the first-open budget, not a flat 10s. |
grok-build Conflict (409) - error sending request / live open timed out after 20s, or Claude Code Agent type 'gemini-3.6-flash-high' not found |
Update to ≥0.1.57 and restart serve. Proven pre-connect misses may switch transport; response-less sends are never replayed. Agent/Task model slugs remap to general-purpose. |
grok-build dumps raw <tool_use> / <parameter> XML, or Cursor auth failed: /usr/bin/security: Too many open files |
Update to ≥0.1.51 and restart serve. Named-parameter XML is recovered as tools; XML spawn_subagent waits for turn end; serve raises the macOS 256-file limit. |
grok-build ends with Cursor finished this turn without text or tool calls, or reports that workflow was intercepted/renamed |
Update to the current release and restart serve. Live heartbeats no longer abort valid thinking at 240s, while a heartbeat-only run with no model progress is bounded to 20 minutes by default. A truly empty Cursor turn still retries instead of becoming successful assistant text; malformed control XML is quarantined; exact workflow/skill casing is preserved. |
grok-build/Grok 4.6 fan-out shows many failed subagents, repeats completed tools, stalls without tokens, or reports rate_limit_error: Cursor live generation concurrency saturated |
Update to the current release and restart serve. Current defaults admit 1024 bulk starts, protect another 128 interactive starts and 64 tool-result resumes, queue overflow fairly for up to 30 seconds, spread conversations across 16 H2 pools, and bound replacement opens to 16. Start a fresh Grok session after upgrading. |
grok-build Conflict (409) - Cursor live open timed out after 20s then many A Cursor live run is already active, or requests stay streaming at 0 B/s |
Update to ≥0.1.65 and restart serve. H2 first-open waits 90s; after one timeout the H2 circuit uses HTTP/1 for 30s, then half-opens with one read-only model-catalog probe. A still-connected duplicate is HTTP 503 + Retry-After; an identical retry whose original consumer is gone attaches to the in-flight run and replays the segment, and a retry of an already-completed turn receives the retained original response. Genuinely ambiguous acceptance remains fail-closed as 409. Start a fresh Grok session after upgrading. |
Cursor produced an empty turn after tool results without a newer checkpoint, or grok-build Conflict (409) - Cursor resume produced no progress after tool results |
Update to ≥0.1.82 and restart serve. A newer post-result checkpoint is continued directly. If Cursor omits it and no text/new tool reached the client, the proxy clears the stale Cursor state and internally retries the same downstream request from the complete Anthropic history, which already contains the finished tool_result. Partial result dispatch or client-visible partial output still remains ambiguity-fenced. |
grok-build reports Cursor tool result wait expired, or a heartbeat stall first appears as 502 and then 409 |
Update to ≥0.1.62 and restart serve. Tool time starts when Grok receives the batch and no longer consumes the next model segment's budget; an already-admitted tool result wins the TTL boundary. Unresolved heartbeat completion is reported as 409 immediately because replay could duplicate the Run. |
Claude Code Bash widget titles a giant python3 -c script |
Update to ≥0.1.48 and restart serve. Cursor Shell has no description; the proxy now fills a short one-line title. |
45s 502 idle timeout / 0 response bytes |
Update to ≥0.1.39 and restart serve. Still set CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK=1. Clash/Surge TUN: DIRECT *.cursor.sh. Optional: CCP_CURSOR_HTTP1=1 |
Stream idle timeout - no chunks received, especially on the first turn or before a background tool result resumes |
Update to the current release and restart serve. /v1/messages commits the Anthropic SSE lifecycle before Cursor live open, so the client receives bytes immediately and emits a watchdog-safe message_delta + ping heartbeat every 5s by default. Pre-output Cursor open/step failures stay inside the bounded retry loop; /v1/responses intentionally keeps held-HTTP mapping for response.failed. |
Gemini/Fable returns ERROR_PRO_USER_RATE_LIMIT_EXCEEDED repeatedly, or Sand says finished this turn without text or tool calls on every resend |
Update to ≥0.1.82 and restart serve. Explicit policy errors and Sand's 100%-meter empty-END sentinel become HTTP 429 with Retry-After; a short cold-key gate stops the first retry wave before it opens many identical Runs. Cooldowns are isolated by stable account, resolved model, and Sand/CLI route, while native tool-result continuations and accepted attaches keep their resume path. |
grok-build context compaction reports idle timeout after 45s with no useful progress / 0 response bytes, or the response parser rejects compaction events |
Update to ≥0.1.82 and restart serve. xai-compact-* and compact_20260112 requests use a stable isolated Cursor live lane, and summaries are emitted as standard Responses assistant/output-text events accepted by Grok Build. |
Claude Code shows Cursor live run cancelled, or Grok 4.6 repeatedly reports A Cursor live run is already active after /compact |
Update to ≥0.1.77 and restart serve. Replacement reservations keep both the old operation fingerprint and its durable Run owner through cancellation teardown; a dropped handoff now seals the existing ledger marker as a scoped ambiguous operation instead of leaving Dispatched state that blocks every later turn. Completed runs are replayed after an attach race and resolved pre-output cancellation is retried inside the same SSE request. |
502 Image not found [internal] on a text-only turn |
Update to ≥0.1.40 and restart serve, then retry the same message once (the poisoned conversation checkpoint is cleared on that error). A new Claude Code session also works. |
502 Conversation data missing / missing blobs and the session cannot recover |
Update to ≥0.1.45 and restart serve, then retry the same message. The failed turn now resets the unrecoverable Cursor conversation binding; the first retry replays full history in a fresh Cursor conversation without requiring a new Claude Code chat. |
400 Missing tool_result blocks for pending tools after an interrupted turn / with background shells |
Update to ≥0.1.45 and restart serve. A new request without current-turn tool results now supersedes the abandoned live turn; partial tool-result batches are still rejected. |
25s 502 broken pipe (reconnect skipped: no checkpoint) on the first message |
Update to ≥0.1.44 and restart serve. First-turn ResumeAction uses conversation_id even before a checkpoint, and broken-pipe H2 flips to HTTP/1. Clash/Surge TUN: DIRECT *.cursor.sh. Optional: CCP_CURSOR_HTTP1=1 |
46s 502 Cursor stream produced no useful progress on Fable high |
Update to ≥0.1.43 and restart serve. Heartbeat-only thinking waits 240s; a fully silent stream still fails at 45s. Clash/Surge TUN: DIRECT *.cursor.sh. Optional: CCP_CURSOR_HTTP1=1 |
502 Cursor live open timed out after 20s / follow-on 90s buffered 502 |
Update to ≥0.1.42 and restart serve. H2 first-open is 20s; HTTP/1 is 90s and only after 464/421. Clash/Surge TUN: DIRECT *.cursor.sh. Optional: CCP_CURSOR_HTTP1=1 |
~8 min 502 error decoding response body |
Update to ≥0.1.41 and restart serve. Reconnect is bounded to 45s. Clash/Surge TUN: DIRECT *.cursor.sh. HTTP proxy mode: CCP_CURSOR_NO_PROXY=1. Optional: CCP_CURSOR_HTTP1=1 |
See CONTRIBUTING.md. Before a PR: cargo fmt, cargo clippy -- -D warnings, cargo test --all.
Security: SECURITY.md.
MIT — includes copyright from the upstream project and this fork’s maintainers.