Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9c6bfe6
feat(adaptation): adapt opencode-cursor for Kilo Code
chiarelli Aug 20, 2026
1f4b28f
feat(auth): make Cursor provider work with Kilo OAuth and authenticat…
chiarelli Aug 20, 2026
5393546
feat(mcp): add Kilo-native MCP passthrough bridge
chiarelli Aug 20, 2026
e80011b
fix(config): accept comments and URLs in JSONC sync-models config
chiarelli Aug 20, 2026
884629f
fix(mcp): enable direct MCP bridge by default and fix cli.json stubs
chiarelli Aug 20, 2026
b536c1f
docs: document Kilo OAuth, MCP passthrough, and CURSOR_KILO
chiarelli Aug 20, 2026
1e19145
feat(sync): populate model limit.context and limit.output during sync
chiarelli Aug 21, 2026
adf6c93
fix(tools): resolve glob and grep stdout maxBuffer errors
chiarelli Aug 21, 2026
b7f4adf
fix(models): preserve cursor-agent wire IDs and versioned model errors
chiarelli Aug 21, 2026
ae63f0d
fix(usage): emit OpenAI-compatible token usage from cursor-agent results
chiarelli Aug 21, 2026
19a10d5
feat(resume): enable session resume by default
chiarelli Aug 21, 2026
8a58c3b
feat(resume): reset cursor session after Kilo compaction
chiarelli Aug 21, 2026
e4899e8
fix(kilo): parse JSONC trailing commas in config files
chiarelli Aug 21, 2026
0c20a78
feat(models): split fast tiers and restore sync pricing
chiarelli Aug 21, 2026
c6d2ed5
Guide Cursor models to Kilo subagents instead of native Task.
chiarelli Aug 24, 2026
946a103
Scope cursor resume cache per Kilo session ID.
chiarelli Aug 24, 2026
1ba88c6
Fix Grok wire ID sanitization and reasoning effort resolution.
chiarelli Aug 29, 2026
55b6e37
fix(usage): omit usage on intermediate tool_calls responses
chiarelli Aug 30, 2026
1cdc07d
feat(mcp): hybrid tool snapshot with fingerprint cache for chat.params
chiarelli Aug 30, 2026
52d193d
feat(mcp): expose Kilo MCP tools through GetDynamicTools
chiarelli Aug 31, 2026
369f57d
docs: translate README to English and document MCP, snapshot, and ses…
chiarelli Sep 1, 2026
27e84b4
Merge branch 'kilocode-adaptation' into kilocode-adaptation-pr
chiarelli Sep 1, 2026
ac173d3
fix(mcp): expose Agent Skills and Composer dynamic tools through the …
chiarelli Sep 12, 2026
91c4fdd
fix(proxy): forward pasted Kilo image and PDF attachments to Cursor
chiarelli Sep 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules/
# Local Kilo sandbox (generated by kilo-cursor install)
local-kilo/
dist/
*.log
.DS_Store
Expand Down Expand Up @@ -49,3 +50,5 @@ TOOL_SMOKE.md
.atl/
estado-fix-sdk.md
plan-fix-sdk.md

**node_modules**
212 changes: 165 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,76 +1,194 @@
<p align="center">
<img src="docs/header.svg" width="828" alt="open-cursor — cursor pro models, inside opencode">
</p>
# kilo-cursor-plugin

<p align="center">
<a href="https://www.npmjs.com/package/@rama_nigg/open-cursor"><img src="https://img.shields.io/npm/v/%40rama_nigg/open-cursor?style=flat-square&color=555&labelColor=333" alt="npm version"></a>
<a href="https://www.npmjs.com/package/@rama_nigg/open-cursor"><img src="https://img.shields.io/npm/dm/%40rama_nigg/open-cursor?style=flat-square&color=555&labelColor=333" alt="downloads per month"></a>
<img src="https://img.shields.io/badge/linux%20%C2%B7%20macos%20%C2%B7%20windows-555?style=flat-square&labelColor=333" alt="linux, macos, windows">
</p>
Transparent bridge between **Kilo Code** and **cursor-agent**, based on [opencode-cursor](https://github.com/Nomadcxx/opencode-cursor).

<p align="center">
<a href="https://nomadcxx.github.io/opencode-cursor/docs/">Documentation</a>
</p>
Kilo is an OpenCode fork. This plugin reuses the same architecture (proxy, streaming, tool loop, `@kilocode/plugin` hooks) with Kilo-specific config, OAuth, and MCP.

`open-cursor` connects OpenCode to the models available through your Cursor
subscription. It translates prompts, streaming responses, thinking, and tool
calls between OpenCode and `cursor-agent`.
Reference: [Kilo Plugins](https://kilo.ai/docs/automate/extending/plugins)

## Installation
## What it does

You need OpenCode, a Cursor subscription, and the `cursor-agent` command.
- Connects Cursor subscription models to Kilo via `cursor-agent` or `@cursor/sdk` (API key)
- **OAuth PKCE** via `kilo auth login --provider cursor` (JWT → cursor-agent; `sk-...` API key → SDK)
- **Maps native tools**: `glob`, `read`, `websearch`, `bash`, and similar Cursor calls → Kilo tools
- **MCP catalog on Kilo names**: `GetDynamicTools` / `GetMcpTools` list the same names Kilo executes (`openviking_search`, `context7_query-docs`, `browser-harness_browser_list_tabs`). No `mcp__` prefix in the visible catalog
- **Hybrid tool snapshot**: polls MCP while servers are pending, then fingerprint-caches `chat.params` so late tools appear without a Kilo reload
- **Session resume** (cursor-agent, on by default): keyed per Kilo session; Cursor chat is reset after Kilo compaction so context-usage % does not stick
- **OpenAI-compatible usage** on final responses (omitted on intermediate `tool_calls` chunks)
- **Subagents**: Cursor `Task` calls are guided to Kilo subagents instead of Cursor-native task types
- **Model sync**: authenticated catalog with fast/standard tiers, pricing, and `limit.context` / `limit.output`
- Hooks: `tool`, `auth`, `chat.params`, `experimental.chat.system.transform`

Install the package and configure OpenCode:
## Prerequisites

- [Kilo Code](https://kilo.ai) CLI ≥ 7.0 or the VS Code extension
- A Cursor subscription and authentication

```bash
npm install -g @rama_nigg/open-cursor
open-cursor install
curl -fsS https://cursor.com/install | bash
kilo auth login --provider cursor
# or: cursor-agent login / CURSOR_API_KEY=sk-...
```

Authenticate and verify the provider:
## Install

### Option 1 — official Kilo command (recommended)

```bash
cursor-agent login
opencode models | grep cursor-acp
kilo plugin kilo-cursor-plugin --global
kilo-cursor install --skip-models
kilo-cursor sync-models
```

The final command should list `cursor-acp/auto`. The installer backs up your
existing OpenCode configuration before writing it and does not touch `.cursor`
by default.
### Option 2 — this package’s CLI

For shell, manual, and source installation, see the
[installation guide](https://nomadcxx.github.io/opencode-cursor/docs/getting-started/installation/).
```bash
npm install -g kilo-cursor-plugin
kilo-cursor install
kilo-cursor sync-models
```

Upgrade with `npm update -g @rama_nigg/open-cursor`, then restart OpenCode.
### Option 3 — local development

```bash
bun install && bun run build
kilo-cursor install
# or symlink local-kilo/.kilo/kilo.jsonc → dist/plugin-entry.js
```

### Resulting config (~/.config/kilo/kilo.jsonc)

```jsonc
{
"$schema": "https://app.kilo.ai/config.json",
"plugin": ["kilo-cursor-plugin"],
"provider": {
"cursor": {
"npm": "@ai-sdk/openai-compatible",
"name": "Cursor",
"options": {
"baseURL": "http://127.0.0.1:32124/v1"
},
"models": { /* sync via kilo-cursor sync-models */ }
}
}
}
```

> **IDs:** `"kilo-cursor-plugin"` in the `plugin` array loads the plugin; `"cursor"` under `provider` registers the model provider (internal provider ID: `cursor`). JSONC comments and trailing commas are accepted when syncing models.

## Usage

Run a prompt with automatic model selection:
```bash
kilo run "Summarize this repo" --model cursor/auto
kilo auth login --provider cursor
```

Pick `cursor/*` in the model picker (reasoning-effort variants when the catalog exposes them).

## Native tool bridge

```
cursor-agent ──glob/read/bash──► proxy (intercept) ──► Kilo executes natively
```

Default mode: `CURSOR_KILO_TOOL_LOOP_MODE=opencode` — Kilo owns the tool list; the plugin only translates `stream-json` → OpenAI `tool_calls`.

## MCP bridge

Two complementary paths. Visible names always match Kilo: `<server>_<tool>`, keeping hyphens (`context7_query-docs`, `openviking_search`, `browser-harness_browser_list_tabs`).

### 1. Passthrough (always on)

MCP registered **in Kilo** (panel, plugins such as OpenViking, `client.mcp.tool.list()` / `client.tool.ids()`):

| Kilo (execution + catalog) | Hidden remap (allowlist only) |
|----------------------------|-------------------------------|
| `context7_resolve-library-id` | `mcp__context7__resolve_library_id` |

- `chat.params` merges tools through a **hybrid snapshot** (`src/mcp/tool-snapshot.ts`): poll while MCP servers are `connecting`/`pending`, then reuse a fingerprint cache
- **`GetDynamicTools`** (and Cursor `GetMcpTools`) returns that catalog, including when Composer queries namespace `"cursor"`. Kilo natives (`agent_manager`, `background_process`, …) and OpenViking `viking_*` wrappers stay on the request/prompt, not in this MCP list
- Hyphen vs underscore aliases collapse to the hyphenated Kilo name (`context7_query-docs`, not both)
- If `mcp.tool.list()` is still empty, the catalog is filled from `client.tool.ids()` and tools already on the proxy wire (plugin MCP such as `openviking_*`)
- **`skill` / `skill_mcp`**: backfilled into `chat.params` and intercepted even as `unknownToolCall`. Call with `skill({ name: "<id>" })` — `name` is required. `CallDynamicTool({ namespace: "kilo", toolName: "skill", arguments: { name } })` is a fallback remap. Listed under **Kilo core tools** in `GetDynamicTools`
- **`CallDynamicTool`** remaps to the Kilo name, including Composer envelopes (`tool_call.function`, `unknownToolCall`). Namespace `"cursor"` (`CreateGoal`, `GenerateImage`, `UpdateGoal`) still runs natively
- Native cursor-agent MCP is always denied via `.cursor/cli.json` `deny: ["Mcp(*:*)"]` (Write/Shell/Edit/Delete are denied only when direct MCP is off)

### 2. Direct MCP (default ON)

Connects servers declared in `kilo.jsonc` → `mcp` over stdio and registers plugin tool hooks:

```jsonc
{
"mcp": {
"my-server": {
"type": "local",
"command": ["npx", "-y", "my-mcp-server"]
}
}
}
```

Disable with `CURSOR_KILO_DIRECT_MCP=false` (legacy alias: `CURSOR_KILO_MCP_BRIDGE=false`).

## Session resume and usage

- **Resume** (`CURSOR_KILO_SESSION_RESUME`, default on, cursor-agent only): maps a Kilo tab to a Cursor `--resume` chat ID. Isolated per Kilo session ID so two chats in the same workspace do not share Cursor state
- After **Kilo compaction**, the cached Cursor chat is dropped so the next turn starts a fresh context window (usage % does not carry over)
- **Pasted images/PDFs** from the Kilo UI are written under `.kilo/cursor-attachments/` and injected as `read` paths (cursor-agent only accepts text stdin)
- **Usage** is emitted in OpenAI-compatible form on the final assistant response; intermediate `tool_calls` chunks omit usage so Kilo does not double-count tokens

## Environment variables

| Variable | Default | Description |
|---|---|---|
| `CURSOR_KILO_TOOL_LOOP_MODE` | `opencode` | `opencode` \| `proxy-exec` \| `off` |
| `CURSOR_KILO_DIRECT_MCP` | `true` | stdio bridge from `kilo.jsonc` `mcp` |
| `CURSOR_KILO_MCP_BRIDGE` | — | Legacy alias of `CURSOR_KILO_DIRECT_MCP` |
| `CURSOR_KILO_MCP_DISCOVERY` | `true` | Poll `mcp.status` until servers settle |
| `CURSOR_KILO_MCP_DISCOVERY_MAX_WAIT_MS` | `2000` | Max wait while MCP is pending |
| `CURSOR_KILO_MCP_DISCOVERY_POLL_MS` | `200` | Poll interval |
| `CURSOR_KILO_MCP_DISCOVERY_STABLE_POLLS` | `2` | Consecutive settled polls required |
| `CURSOR_KILO_SESSION_RESUME` | `true` | cursor-agent `--resume` cache |
| `CURSOR_KILO_BACKEND` | `auto` | `auto` \| `cursor-agent` \| `sdk` |
| `CURSOR_KILO_BRIDGE_JSON` | `true` | JSON bridge for the `write` tool |
| `CURSOR_KILO_PROVIDER_BOUNDARY` | `v1` | Tool-intercept boundary |
| `KILO_PURE=1` | — | Disable external plugins (Kilo docs) |

The legacy `CURSOR_ACP_*` prefix is still read in several places.

## Commands

```bash
opencode run "Summarise this repository in five bullets." \
--model cursor-acp/auto
kilo-cursor install # cursor provider + plugin
kilo-cursor sync-models # authenticated models (Kilo OAuth / API key)
kilo-cursor status
kilo-cursor doctor
mcptool tools # debug direct MCP bridge
kilo-cursor uninstall
```

You can also start `opencode` and choose a `cursor-acp/*` model from its model
picker.
## Further documentation

## Documentation
| File | Contents |
|---|---|
| [docs/architecture/runtime-tool-loop.md](docs/architecture/runtime-tool-loop.md) | Tool loop, boundary, bridge JSON |
| [docs/cursor-agent-tools.md](docs/cursor-agent-tools.md) | cursor-agent tool inventory |
| [docs/architecture/cursor-acp-mcp-future.md](docs/architecture/cursor-acp-mcp-future.md) | ACP/MCP roadmap (reference) |

- [Installation](https://nomadcxx.github.io/opencode-cursor/docs/getting-started/installation/)
- [Authentication](https://nomadcxx.github.io/opencode-cursor/docs/getting-started/authentication/)
- [Configuration](https://nomadcxx.github.io/opencode-cursor/docs/reference/configuration/)
- [Choosing a model](https://nomadcxx.github.io/opencode-cursor/docs/guides/choosing-a-model/)
- [MCP servers](https://nomadcxx.github.io/opencode-cursor/docs/guides/mcp-servers/)
- [Troubleshooting](https://nomadcxx.github.io/opencode-cursor/docs/getting-started/troubleshooting/)
- [Architecture](https://nomadcxx.github.io/opencode-cursor/docs/architecture/overview/)
- [Development](https://nomadcxx.github.io/opencode-cursor/docs/development/building/)
Docs under `docs/architecture/*` whose names start with `opencode` or `cursor-acp` describe the upstream fork or historical decisions. The Kilo runtime uses `CURSOR_KILO_*` and provider ID `cursor`.

## License
## Development

BSD-3-Clause
```bash
bun install
bun run build
bun test
kilo --print-logs --log-level DEBUG
```

---
After changing `src/`, rebuild (`bun run build`) and restart Kilo. If the plugin is installed from `~/.config/kilo/plugin/kilo-cursor-plugin`, copy sources there and rebuild that copy — Kilo loads `dist/plugin-entry.js`, not TypeScript.

<a href="https://github.com/Nomadcxx"><img src="https://raw.githubusercontent.com/Nomadcxx/Nomadcxx/main/assets/rama-mark.svg" height="22" alt="RAMA"></a> — terminal-native tooling for the linux desktop.
[More projects →](https://github.com/Nomadcxx) · [Sponsor](https://github.com/sponsors/Nomadcxx) ❤️
## License

BSD-3-Clause
21 changes: 21 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Documentation index

Operational docs (kept current for Kilo Code):

| Doc | Description |
|-----|-------------|
| [architecture/runtime-tool-loop.md](architecture/runtime-tool-loop.md) | Proxy, tool loop, MCP bridge, auth |
| [cursor-agent-tools.md](cursor-agent-tools.md) | cursor-agent tool inventory + MCP mapping |
| [PUBLISHING.md](PUBLISHING.md) | npm publish checklist |

Historical / strategic (OpenCode / cursor-acp era; env vars may say `CURSOR_ACP_*` or `open-cursor`):

| Doc | Description |
|-----|-------------|
| [architecture/opencode-skills-bridge-design.md](architecture/opencode-skills-bridge-design.md) | Original skills bridge design |
| [architecture/cursor-acp-mcp-future.md](architecture/cursor-acp-mcp-future.md) | ACP + MCP decision gate |
| [architecture/cursor-acp-mcp-readiness.md](architecture/cursor-acp-mcp-readiness.md) | Redirect to future doc |
| [architecture/harness-ecosystem-survey.md](architecture/harness-ecosystem-survey.md) | Ecosystem survey |
| [RELEASE_NOTES.md](RELEASE_NOTES.md) | Upstream release history |

Current Kilo plugin defaults: provider ID `cursor`, env prefix `CURSOR_KILO_*`, CLI `kilo-cursor`.
Loading