All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Request timing markers for runtime diagnostics.
- Status output now shows runtime settings.
- Quota banners are suppressed after a successful stream.
- Quota-exit tests now let mocked stdio flush before termination.
- Cursor-agent runner pool behind
CURSOR_ACP_AGENT_POOL, including request cancellation via runner control messages.
- Session resume now validates branch matching, tool fingerprints, prompt anchor hashes, and stale chat IDs more defensively.
- Runner pool lifecycle now evicts idle runners and hardens cancellation, CI registration, and log safety.
- Issue #92 verification cleanup now uses safer test paths.
- Session resume for multi-turn cursor-agent requests.
- Reduced per-request proxy overhead by caching tool schema blocks, reusing config path resolution, replacing synchronous file logging with a write stream, avoiding SDK demux re-stringify, and disabling Nagle on SSE sockets.
OPENCODE_CONFIGis now respected by theopen-cursorCLI.- Logger stream handling is guarded after rotation failures.
- Tool schema cache fingerprints now include stronger request-shape details.
- Subagent cache gating now uses a nullish check.
- Content edit payloads are guarded before being forwarded, avoiding unsafe malformed edit requests.
- Model refresh controls for compact model updates.
- Guarded stream-content edits and partial file overwrite paths so malformed Cursor edits do not accidentally replace whole files.
- OpenCode plugin imports now use the tool subpath expected by newer plugin packaging.
- Proxy health checks now time out instead of hanging indefinitely.
- Empty
edit.old_stringvalues are rejected before execution.
- README install flow and ACP/MCP roadmap documentation were streamlined.
- Authentication: API key authentication now supports three methods with priority: (1)
CURSOR_API_KEYenvironment variable, (2) OpenCode auth store (opencode auth login --provider cursor-acp), (3) provider options inopencode.json. Get your API key from cursor.com/settings. Legacy OAuth flow viacursor-agent loginis no longer supported.
- Runtime: Replaced the
cursor-agentbinary (removed by Cursor in IDE versions >= 0.43) with the official@cursor/sdk. The SDK runs in a persistent Node.js child process (scripts/sdk-runner.mjs) instead of in-process, because the SDK's ConnectRPC/HTTP2 stack hangs inside OpenCode's embedded Bun runtime and its nativesqlite3dependency cannot be bundled. The persistent process avoids paying Node boot + SDK import cost on every request. - SDK Agent isolation: The Agent now runs isolated from the Cursor environment by default (
settingSources: []), no longer loading user/project/team/mdm/plugins rules and skills per request. This eliminates duplicate instructions between Cursor and OpenCode and reduces request latency. To restore the previous behavior, setCURSOR_ACP_SETTING_SOURCES=all, or specify a subset likeuser,project. - Tool calls: The SDK emits MCP tool calls as a generic tool named
mcpwith{providerIdentifier, toolName, args}; the runner remaps them to themcp__<server>__<tool>names OpenCode expects, so MCP tools are executed instead of rejected as unavailable. - Model discovery:
/v1/modelsand the startup auto-refresh now queryCursor.models.list()from the SDK (via the runner) instead of the removedcursor-agent modelscommand. Newly released Cursor models are added toopencode.jsonautomatically (additive only), with an updated hardcoded fallback when no API key is available. - Installation: New local development workflow via
scripts/install-plugin.sh, which creates a TypeScript wrapper at~/.config/opencode/plugins/cursor-acp.tspointing at the repository entry point.
- Issue #76 (ECONNREFUSED on 127.0.0.1:32124): the proxy failed to start because the plugin spawned the removed
cursor-agentbinary. The plugin now works withoutcursor-agentinstalled. - The system prompt no longer suggests an ambiguous
mcptool name; full tool names are listed explicitly, and a defensive guard logs any remaining baremcpcalls. - Local tool hooks now register
oc_*aliases and use safe context defaults. - AskQuestion calls are routed to the OpenCode
questiontool.
- Per-request latency is bound by
@cursor/sdkitself (Agent.create+sendtake ~6s even standalone). Each request uses a fresh Agent by design: conversation state stays in OpenCode and is never persisted on Cursor's side. - Node.js >= 20 must be available in
PATH(the SDK runner requires it).
- MCP tool guidance now recommends direct
mcp__<server>__<tool>calls instead of themcptoolCLI, and prompts list exact MCP tool names.
- Malformed full-file edits are rerouted to
writeinstead of being treated as partial edits.
- Windows binary paths are quoted before execution.
- Mixed partial stream output is handled correctly.
- Duplicate streaming output from
cursor-agentis prevented.
- Native
grepbehavior is preserved when falling back through tool compatibility layers.
- Empty edit replacements are rejected to prevent destructive file rewrites.
- CLI startup now handles symlinked
binentrypoints.
- Command tool execution now uses the platform shell, improving Windows compatibility.
- Windows platform support, including executable path resolution, spawn compatibility, case-insensitive workspace comparisons, and Node.js fallback
grep/globimplementations. - Cursor usage metrics forwarding.
- Official Cursor model pricing metadata and a pricing coverage check.
- Runtime support for Cursor model variants.
- Refreshed the model lineup and pointed users to the sync-models CLI workflow.
syncpreserves user-set model costs and trims npm package files.
- Workspace detection rejects
/as a Cursor workspace and falls back to$HOME. - Final thinking snapshots are deduplicated and final thinking text is replaced for parity with assistant messages.
z.record()usage is compatible with Zod v4.- Windows docs and provider tests were corrected.
- Task tool subtype values are injected into system messages so Cursor emits valid task calls.
- Available task execution targets can now be listed from config.
- Task tool loop-guard handling now uses a higher exploration threshold and soft-blocks on first trigger instead of killing the stream immediately.
- Regenerated a complete
package-lock.json.
@opencode-ai/pluginandzodare externalized to prevent bundled Zod v4 class conflicts.
- Bash tool execution now uses
spawn(), correct timeout units, and proper non-zero exit handling.
- MCP tool bridge with
mcptoolCLI for Shell-based MCP tool execution.
- README now documents the MCP tool bridge and updates the roadmap and architecture diagram.
- Model list auto-refresh at plugin startup.
- Partial streaming detection now only sets the partial-output flag when the partial has content.
StreamJsonAssistantEventnow includestimestamp_mswithout relying onas anycasts.
- Cursor-agent partial delta events no longer produce duplicated responses.
DeltaTrackerno longer duplicates output when accumulated prefixes drift.
webfetchis classified as an exploration tool for loop-guard handling.
bashandshellare classified as exploration tools for loop-guard fingerprinting.
- Success-path loop-guard tests now account for the exploration tools multiplier.
- Exploration tool multiplier is applied to successful tool-call loop-guard paths.
- Discovered pass-through tools are treated as known-success tools for loop-guard accounting.
- Exploration tools are exempt from coarse fingerprint tracking to avoid false loop detections.
- Tool loop guard coarse fingerprint was too aggressive, blocking legitimate multi-file exploration ("3 attempts limit 2"). Coarse limit now 3x higher (6 vs 2).
- Tool loop guard no longer speculatively inflates counts from stripped conversation history.
- Plugin loading crash caused by OpenCode loader calling class constructors without
new. Entry point now isolated to single default export inplugin-entry.ts.
- MCP tool pass-through: unknown tools (e.g. Playwright via cursor-agent) are tracked instead of dropped, with toast notifications summarizing activity at response end.
PassThroughTrackerfor tracking forwarded tool calls and errors.ToastServicefor OpenCode TUI toast integration with graceful degradation.extractOpenAiToolCallnow returns structured result withactionfield (intercept/passthrough/skip).
- Removed stale implementation docs (
docs/implementation/).
- Tool loop guard now detects repeated successful
edit/writeloops (including coarse path-based repeats) while reducing false positives. - Schema-validation loop-guard history is now seeded from tool-call shapes even when tool result messages are missing/truncated.
- SSE streaming conversion now emits assistant text deltas from both partial and non-partial assistant events.
- Proxy port selection now probes for an actually-bindable port, avoiding reliance on incomplete
ss/lsofoutput.
- Plugin directory initialization now respects
XDG_CONFIG_HOME(createsopencode/pluginunder the configured XDG config home).
- README now uses
npm exec -- @rama_nigg/open-cursor ...examples to avoid PATH issues with global npm bin. - Removed README references to
open-cursor sync-modelsandopen-cursor status(useinstallto resync models).
- Clarified npm install instructions and removed “check npm view first” from README.
- CLI help output now matches the invoked binary name (
open-cursor).
- Prefer OpenCode
worktree(andOPENCODE_CURSOR_PROJECT_DIR) when selecting the Cursor workspace directory, avoiding writes being scoped to~/.config/opencodeon macOS. - Tool hook path resolution now prefers
context.worktreeand ignores OpenCode config-dircontext.directorywhen resolving relative paths.
- OpenCode-owned tool loop adapter for OpenAI-style
tool_callsresponses (src/proxy/tool-loop.ts) - Focused integration coverage for request-1/request-2 tool loop continuity (
tests/integration/opencode-loop.integration.test.ts) - CI test split scripts:
test:ci:unitandtest:ci:integration - GitHub Actions job summaries for unit and integration suites
- Packaging CLI entrypoint
open-cursorfor npm/global installs (src/cli/opencode-cursor.ts) - Model discovery parser utility for CLI install/sync workflows (
src/cli/model-discovery.ts)
- CI workflow split into separate
unitandintegrationjobs - Integration CI defaults to OpenCode-owned loop mode (
CURSOR_ACP_TOOL_LOOP_MODE=opencode) - npm package metadata now targets publish/install as
open-cursor - Build now emits CLI artifacts for package bins (
dist/opencode-cursor.js,dist/discover.js)
- Node proxy fallback after
EADDRINUSEnow recreates the server before dynamic port bind - Streaming termination guards prevent duplicate flush/output after intercepted tool call
- Auth unit tests now clean all candidate auth paths to avoid environment-dependent flakes
- Provider config generator no longer hardcodes a local filesystem npm path
- Added auth home-path override (
CURSOR_ACP_HOME_DIR) for deterministic auth path resolution in tests/automation - Added proxy reuse toggle (
CURSOR_ACP_REUSE_EXISTING_PROXY) to avoid accidentally attaching to unrelated local proxy servers
- New streaming module (
src/streaming/) with proper NDJSON parsing LineBufferutility for handling TCP chunk boundaries in streaming responsesDeltaTrackerfor deduplicating accumulated assistant textStreamToSseConverterfor OpenAI-compatible SSE formattingStreamToAiSdkPartsfor ai-sdk stream part generation- Thinking event support with
subtype: "delta"andsubtype: "completed" - Tool call streaming with
started,completed, andfailedstates - Integration tests for streaming pipeline validation
- New exports:
LineBuffer,parseStreamJsonLine,DeltaTracker,StreamToSseConverter,formatSseChunk,formatSseDone,StreamToAiSdkParts
- Streaming responses now arrive incrementally instead of buffering until completion
- Switched from
--output-format textto--output-format stream-json --stream-partial-output - Provider now properly handles
tool_callandthinkingevents - Plugin SSE output now correctly formats parsed events instead of raw bytes
- Assistant text deduplication prevents re-sending full accumulated content
SimpleCursorClient.executePromptStream()now yieldsStreamJsonEventobjects- Plugin Bun and Node.js streaming paths use new line buffer and SSE converter
- Provider direct-mode streaming uses new ai-sdk parts converter
Initial release with stdin-based prompt passing to fix E2BIG errors.