Files
olp/docs/integrations/cursor.md
53afea47ca feat+test+docs: D71+D72+D73 — olp-plugin/ (OpenClaw /olp Telegram+Discord) + docs/integrations/*.md + README cross-refs (#44)
Final Phase 4 substantive D-day group. 3 D-days bundled per Iron Rule 11
IDR (plugin consumes existing endpoints; integration docs reference plugin
+ olp CLI + olp-connect together; README index links all).

After this PR merges, Phase 4 has shipped all 5 D-day groups (D60 charter
+ port / D61-D63 SSE heartbeat+ring+/status / D64-D67 olp CLI+doctor /
D68-D70 olp-connect+anonymous-key+ADR0011 / D71-D73 plugin+docs). The
v0.4.0 close PR is maintainer-triggered per CLAUDE.md release_kit overlay.

## D71 — olp-plugin/ (OpenClaw gateway plugin)

Port OCP ocp-plugin/index.js (311 lines) → OLP olp-plugin/index.js (482
lines) as the /olp Telegram+Discord slash command, but MINUS mutations
(no /olp keys keygen, no /olp keys revoke, no /olp restart, no /olp logs
— all of these require SSH out of chat for security).

Plugin shape:
- olp-plugin/index.js — registers /olp command via OpenClaw api.registerCommand
- olp-plugin/openclaw.plugin.json — manifest, apiKey REQUIRED, proxyUrl
  default http://127.0.0.1:4567 (matches D60)
- olp-plugin/package.json — minimal: name/version/type:module + OpenClaw
  discovery block
- olp-plugin/README.md — install + configure + use docs; documents the
  "no mutations from chat" security stance and the dedicated-bot-key
  pattern (don't share maintainer's personal key with the bot)

Subcommand parity with olp CLI (D64-D67):
- /olp status   → GET /v0/management/status         (owner-only)
- /olp health   → GET /health                       (public-ok)
- /olp usage    → GET /v0/management/dashboard-data (owner-only)
- /olp models   → GET /v1/models                    (public-ok)
- /olp cache    → GET /cache/stats                  (owner-only)
- /olp providers → local cross-ref                  (public-ok)
- /olp chain show [<model>] → local                 (public-ok, advisory
  if no FS access — defer to ssh + olp chain show)
- /olp doctor   → informational (HTTP doctor endpoint deferred; advisory
  to ssh + olp doctor for live use)
- /olp help     → usage text

Port resolution: OLP_PROXY_URL env → OLP_PORT env → plugin config
proxyUrl → http://127.0.0.1:4567. Output: Telegram/Discord monospace
code block with status icons (🟢🟡🔴). Long responses truncated for the
4096-char message limit.

No npm deps. OpenClaw provides Telegram/Discord transport; plugin uses
fetch + node builtins only.

## D72 — docs/integrations/*.md (6 IDE pages + index)

Per the Phase 4 brainstorm prior-art survey + ADR 0010 § Out-of-scope
posture for Claude Code:

- continue.md    — config.yaml (NOT config.json); apiBase; requestOptions.headers
- cline.md       — "OpenAI Compatible" provider; Cline #7128 base-URL UI bug warning
- cursor.md     ⚠️  — known base-URL fragility; only enable models OLP serves
- aider.md       — OPENAI_API_BASE env + openai/ prefix; .env support
- claude-code.md  — explicitly NOT supported per ADR 0010 § /v1/messages defer
                     rationale; recommended alternative: Cline + OLP
- openclaw.md    — install olp-plugin via CLI or symlink; configure apiKey;
                    restart gateway

Each ~60-120 lines: status / quick setup / known issues / OLP-specific
notes / test-it command. docs/integrations/README.md is the index.

## D73 — README cross-references

- New § "IDE Setup" links to docs/integrations/README.md
- New § "Telegram / Discord Usage" — install + configure + restart + use
- Quick Start mentions olp-connect <ip> as family-onboarding command
- package.json `files` field extended to include olp-plugin/ so the
  published tarball ships the plugin

## Test count

672 → 696 (+24 D71-D73 tests in Suite 35: helpers / formatters /
dispatch / error paths). All 696 pass locally.

## Scope discipline

- server.mjs UNTOUCHED (plugin consumes EXISTING endpoints)
- No new npm deps (no Telegram or Discord SDK — OpenClaw provides transport)
- No /v1/messages (out of Phase 4 per ADR 0010)
- No CHANGELOG / package.json version bump (Phase 4 close handles versioning;
  only package.json `files` extended for olp-plugin/ publication)

## Implementor flagged for reviewer

1. /olp doctor returns SSH advisory (no HTTP doctor endpoint yet). When
   future phase exposes /v0/management/doctor, swap advisory branch for
   real fetchJSON + fmtDoctor (already implemented + tested).
2. /olp providers + chain show have no FS access (plugin runs in OpenClaw
   gateway process); registry read via lazy-imported models-registry.json
   from repo root. For live enabled-state visibility users still need
   /olp status (owner-tier) or ssh + olp providers / olp chain show.
3. No live-server wire test in Suite 35 — existing Suites 31/32 already
   cover the integration path against the same endpoints; mock-fetch in
   Suite 35 is sufficient signal for the plugin layer.

## Authority

- ADR 0010 § Phase 4 D-day plan D71-D73 line
- OCP ocp-plugin/index.js (port reference)
- ADR 0010 § Out-of-Phase-4-scope (claude-code.md  rationale)
- 2026-05-26 brainstorm (Top OCP inheritance candidates + prior-art
  survey IDE-specific quirks for cline/cursor/continue docs)

Co-authored-by: dtzp555 <dtzp555@gmail.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 09:35:23 +10:00

4.4 KiB

Cursor + OLP

Cursor is an AI-first VS Code fork. It has an "Override OpenAI Base URL" setting that, when populated, routes its default-model traffic to your URL using the OpenAI wire format.

Status: ⚠️ Best-effort.

Reason: Cursor's base-URL override is known to be fragile across releases. Multiple 2025-2026 forum threads document the setting silently reverting, model-list dropdowns not populating from the override URL, and streaming responses falling back to the default backend on parse errors. The behaviour is not specific to OLP — every OpenAI-compatible proxy maintainer documents the same caveats — but Cursor's release cadence is faster than most third-party proxies can test against.

Quick setup

  1. Open Cursor → Settings → "Models" → enable OpenAI API Key.

  2. Paste your OLP plaintext token into the API Key field.

  3. Click "Override OpenAI Base URL" and paste:

    http://127.0.0.1:4567/v1
    
  4. Click "Verify". Cursor sends a probe; on success the indicator turns green.

  5. Crucial step: in the model list, disable every model that is NOT in your ~/.olp/config.json routing.chains. Cursor's chat will round- robin across enabled models and any model OLP can't route will error.

Replace the API key with the plaintext token printed by olp-keys keygen --name=cursor. Family members on the LAN should substitute the OLP host's IP for 127.0.0.1 (or use olp-connect <ip>).

Known issues

  • Override URL silently reverts on Cursor update. Two reported variants: (a) the field empties; (b) the field shows the OLP URL but Cursor still hits api.openai.com under the hood. Workaround: after every Cursor update, re-open settings, click "Verify" again, and check the OLP server's /health for incoming probe requests.

  • Model-list dropdown does not populate from the override URL. Cursor hardcodes its model list rather than reading GET /v1/models. This is why step 5 above is required — there is no way to make Cursor "discover" your models. You have to disable each model individually that OLP can't serve.

  • Streaming response parsing is stricter than OpenAI's actual SSE spec. Cursor occasionally falls back to the default backend if the SSE stream contains a slightly malformed chunk (e.g. an empty data: line that OpenAI's API does emit but Cursor's parser doesn't expect). OLP's SSE emitter follows the spec; this is on Cursor's side. If you see traffic hitting api.openai.com despite the override, this is the most likely cause.

  • Cursor's "Tab" autocomplete is NOT covered by the override. Tab completion uses a Cursor-proprietary endpoint that is not affected by the OpenAI base URL setting. Only the chat panel is. This is documented Cursor behaviour and is not a bug.

OLP-specific notes

Cursor sends model: "gpt-4" or model: "gpt-3.5-turbo" (legacy aliases) unless you explicitly select another from its dropdown. Add aliases to your ~/.olp/config.json routing.chains so these route somewhere sane:

{
  "routing": {
    "chains": {
      "gpt-4":         [ { "provider": "openai", "model": "gpt-5" } ],
      "gpt-3.5-turbo": [ { "provider": "openai", "model": "gpt-5-mini" } ]
    }
  }
}

(Substitute the OpenAI Codex model names listed by olp models.)

Recommendation

Do not engineer workarounds for Cursor-side bugs. Cursor's release cadence will fix or re-break the override URL handling at unpredictable intervals. If your daily-driver flow is unreliable, switch to Cline (see cline.md) — it has a stable OpenAI-compatible provider that does not break across releases.

Test it

curl -sI -X POST http://127.0.0.1:4567/v1/chat/completions \
  -H "Authorization: Bearer olp_XXXXXX" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-4","messages":[{"role":"user","content":"ok"}],"max_tokens":5}' \
  | grep -i x-olp

After hitting "Send" in Cursor's chat, check the OLP server's recent requests via:

npx olp logs 10

If you don't see Cursor's request in the audit log, traffic isn't reaching OLP — re-check the override URL.

Cross-references

  • Cursor forum threads on base-URL fragility: https://forum.cursor.com/ (search "OpenAI base URL")
  • olp-connect writes Cursor's cursorrc if detected, but cannot guarantee the override survives a Cursor update.