Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>xnes — Next Edit SuggestionsNew to Visual Studio Code? Get it now.
xnes — Next Edit Suggestions

xnes — Next Edit Suggestions

ali50m

|
1 install
| (0) | Free
Next edit suggestions powered by your own OpenAI-compatible endpoint.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

xnes

Next Edit Suggestions for VS Code, powered by any OpenAI-compatible /chat/completions endpoint.

This extension uses the proposed inlineCompletionsAdditions API. Marketplace may reject proposed-API extensions; Open VSX and supported VS Code hosts can still use the VSIX.

Requires VS Code 1.128 or newer. The full feature set is validated on VS Code 1.143.1; Cursor 3.25.6 (VS Code 1.128.0) can run the basic inline-edit path with reduced lifecycle features.

Features

  • Cursor-local next edit suggestions rendered as VS Code inline edits or ghost text.
  • Streaming <EDIT> / <INSERT> / <NO_CHANGE> protocol with truncation protection.
  • Response hardening: preserves blank lines, strips echoed prompt markers, aligns whole-file replies to the edit window, and does not delete trailing lines the model omitted.
  • Continuous-tab cache: after accepting one edit, subsequent edits are served from the same model response without another request, even after small unrelated edits in between.
  • File-switch trigger: switching files shortly after accepting a suggestion asks for a new one; ordinary file switches do not.
  • Adaptive end-of-line debounce for slower typing (xnes.debounce.adaptive).
  • Partial accept continues the cached sequence for inserts and replacements when the resulting document state matches; ambiguous states are discarded.
  • XNES: 试运行 runs the production pipeline and logs the result without showing a suggestion or modifying the document.
  • Experimental searchReplace response format (xnes.model.responseFormat): the SEARCH fragment must occur once in the edit window, and truncated streams are discarded.
  • Experimental codeBlock response format: a fenced window that reuses the streaming diff and truncation protection.
  • Experimental next-cursor jump (xnes.experimental.nextCursorJump): after accepting an edit, move the cursor to the next edit predicted in the same response. Off by default.
  • Experimental speculative prefetch (xnes.experimental.prefetchAfterAccept): after accepting an edit, warm the cache for the next position in the background when no follow-up edit is cached. Off by default and consumes extra API quota.
  • Experimental cross-file prefetch (xnes.experimental.crossFilePrefetch): after accepting an edit, pre-warm a suggestion for the most recently edited other open file (up to crossFilePrefetchMax). When you switch there, the cached suggestion is labeled with its origin through the proposed displayLocation API; a transient status-bar hint links to the target file. Off by default.
  • Per-endpoint API keys in SecretStorage; endpoints and model names in globalState.
  • Parameter fallbacks are persisted per endpoint, and diagnostics reports p50/p90 latency from a rolling sample buffer.
  • Webview settings panel with model discovery, a production-pipeline speed test, and advanced response-format / recent-file / adaptive-debounce / next-cursor / prefetch / cross-file controls. The panel separates editing an endpoint from making it active, keeps drafts and caret position across updates, shows inline validation, and groups advanced options into collapsible sections.
  • Status bar shows the active model plus session shown/accepted counts. Clicking it opens a menu for settings, model selection, per-workspace / global enable toggles, logs and diagnostics; a gear item opens settings directly.
  • Speed test covers five cases and reports separate cold/warm medians.
  • Privacy filters: workspace trust, .env/keys/lockfiles, size limits, binary files.
  • Recent-file context from other edited files, bounded by token and file caps.
  • Proxy support through VS Code http.proxy / http.proxyStrictSSL and http.noProxy, falling back to HTTP(S)_PROXY / NO_PROXY.
  • Request cancellation, deduplication, minimum interval and per-minute rate limits.

Install

Store installs (VS Code Marketplace, Open VSX, Cursor) work out of the box: settings, model selection, diagnostics, dry run and inline suggestions are registered. Because a store install is not listed in the host's product.json#extensionEnabledApiProposals, the host silently drops the extension's enabledApiProposals and the proposed inline-completion lifecycle is limited (no continuous-tab acceptance, cross-file labels or next-cursor jump, and classic ghost text cannot rewrite text before the cursor).

Run XNES: 启用完整内联建议(写入 argv.json) from the command palette to grant the proposal; the command patches argv.json and asks for a full restart. The same can be done manually:

  • VS Code: ~/.vscode/argv.json (Insiders: ~/.vscode-insiders/argv.json)
  • Cursor: ~/.cursor/argv.json
{
  "enable-proposed-api": ["ali50m.xnes"]
}

Then restart the editor and disable Copilot NES if both extensions are installed.

Install from a VSIX (local)

code --install-extension xnes-1.0.2.vsix

Cursor 3.25.6

Cursor 3.25.6 embeds VS Code 1.128.0. ~/.cursor/argv.json (on Windows: C:\Users\<user>\.cursor\argv.json) grants the proposal as shown above. Then restart Cursor and disable Cursor's own Tab/NES if both are active.

On 1.128, basic inline edits work, but the host does not provide handleEndOfLifetime, handleListEndOfLifetime, displayLocation or jumpToPosition. Continuous-tab acceptance, cross-file labels, next-cursor jump and accepted-count metrics are therefore degraded; the status bar may show accepted counts as 0. VS Code 1.143+ keeps the full behavior.

Commands

Command Description
XNES: 打开设置 Endpoint, key, model, speed test
XNES: 选择模型 Model QuickPick / open settings
XNES: 立即请求建议 Explicit trigger
XNES: 试运行(不显示建议) Run the pipeline and log the result without changing the editor
XNES: 诊断 Proposed API, Copilot conflicts, proxy, metrics
XNES: 在此工作区启用/禁用 Per-workspace kill switch
XNES: 全局启用/禁用 Global xnes.enabled switch
XNES: 显示日志 Output channel
XNES: 启用完整内联建议(写入 argv.json) Grant the proposed API without editing argv.json by hand

Development

npm install
npm run check        # tsc --noEmit
npm test             # vitest unit tests
npm run build        # dist/extension.js + dist/webview
npm run test:integration        # extension development host, proposed API enabled
npm run test:integration:store  # same suite without --enable-proposed-api
npm run package

Integration tests download VS Code 1.143.1 into .vscode-test/ and run against a local mock OpenAI server. test:integration:store reproduces a store install by withholding --enable-proposed-api, which makes the host strip package.json#enabledApiProposals exactly like the Marketplace and Open VSX do. Keep both modes green: activation and every command must work in store mode.

Publishing

.github/workflows/publish.yml publishes the same VSIX to the VS Code Marketplace and Open VSX. It runs manually or on a v* tag, and expects the VSCE_PAT and OVSX_TOKEN repository secrets. See docs/publishing.md.

Offline evaluation

Use any OpenAI-compatible endpoint. The API key can come from XNES_API_KEY instead of the command line so it does not end up in shell history:

$env:XNES_BASE_URL = "https://api.example.com/v1"
$env:XNES_MODEL = "my-model"
$env:XNES_API_KEY = "sk-..."

node test/eval/run.mjs

Or keep the values in a local, gitignored file so a new shell or the agent can read them without exporting anything (see test/eval/env.example):

# test/eval/.env.local
XNES_BASE_URL=https://api.example.com/v1
XNES_MODEL=my-model
XNES_API_KEY=sk-...

The runner reads test/eval/.env.local by default; use --env-file <path> for another location. Command-line flags win over process environment, which wins over the file.

Or pass everything explicitly:

node test/eval/run.mjs --base-url https://api.example.com/v1 --api-key $env:KEY --model my-model --format unifiedXml

--format also accepts searchReplace and codeBlock. Single-file cases live in test/eval/cases/; results are written to test/eval/.results/latest.json.

Cross-file cases live in test/eval/cross-file-cases/. They seed history with a source-file edit, run the normal pipeline on a target file, and compare the result with a hand-written expected target:

node test/eval/run.mjs --cross-file --runs 3

--runs repeats each case to estimate a stable hit rate; each run is a real model request. Results are written to test/eval/.results/latest-cross-file.json. Add --cross-file-only to skip the single-file suite while tuning cross-file behavior. Use --case <name> to run one case.

Useful tuning flags (both modes):

node test/eval/run.mjs --cross-file-only --runs 5 --recent-files 5 --recent-tokens 2000 --temperature 0 --max-output-tokens 512

The runner reports strict exact and semantic matches. semantic ignores blank-line and trailing-whitespace differences, which distinguishes formatting drift from wrong code. latest.json and latest-cross-file.json also include the raw response and edit details for each attempt.

  • --recent-files / --recent-tokens change how much other-file context the prompt carries; for cross-file cases these are the main knobs.
  • --temperature defaults to 0 for reproducible evaluation.
  • --max-output-tokens defaults to 512.

Measured baseline on 2026-10-25 with JIUTIAN-75B-32K, unifiedXml, temperature 0:

Suite Result
Single-file format 100%, exact 100% (12/12), semantic 100%, no-change 100%, destructive 0
Cross-file (--runs 5) exact 100% (15/15), semantic 100%, format 100%, destructive 0

Single-file initially missed multi-line-py: the model returned only part of the edit window. The user postscript now requires the complete window, including blank and unchanged lines, and two consecutive full runs matched 12/12 with no destructive edits. Cross-file initially failed on blank-line formatting and missing import updates; preserving blank lines, allowing import-only propagation, and giving the cross-file prompt a larger window moved it to 100%.

For a quick mock smoke test, point --base-url at any local SSE server that returns <NO_CHANGE> or a valid <EDIT>; the runner does not require a real provider.

The runner entry is test/eval/runner.ts; CLI/env parsing, fixtures, scoring, engine setup, and result writing live in separate modules, and the single-file and cross-file suites are under test/eval/suites/.

Live multi-file smoke test

With a real endpoint in test/eval/.env.local, run the extension inside a real VS Code test host:

npm run test:live

This opens copies of the repo's rename-export-ts cross-file fixture, renames the source export, runs the real cross-file prefetch, and verifies that the target suggestion is served from cache with the Cross-file next edit displayLocation label. It does not modify tracked files.

A rename on arbitrary src/ files is also possible, but the current model returned no suggestion for the applyEdits and CrossFileStore.remember experiments; use the manual checklist for those larger, intent-driven changes.

Architecture

See dev.md (Chinese) for the full contract. The short version:

provider.ts (VS Code adapter)
  → requestCoordinator (policy, debounce, dedupe, cancel, rate limit, cache)
  → nextEditEngine (prompt → SSE → parser → streaming diff → filters)
  → vendor/vs (ported edit algebra for safe offset mapping)

Core modules under src/core/ never import vscode.

Privacy

The prompt contains only the cursor-local current-file excerpt, recent edit diffs, the surrounding code window with a relative path, and short excerpts around recent edits in up to five other files (set xnes.prompt.recentFilesMax to 0 to disable the last part). Only relative paths are sent; excluded files never enter history or the prompt. Endpoints, model names and keys cannot be changed from settings.json or a workspace's .vscode/settings.json; they are only written by the settings webview. Only the user/machine http.proxy value is honored; workspace proxy overrides are ignored. Prompt logging is off by default (xnes.log.includePrompt). Speculative prefetch is off by default; when enabled it sends the same bounded prompt after you accept a suggestion, without showing anything. Cross-file prefetch is also off by default and only targets files that already passed the history/privacy filters.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft