Skip to main content
Source-backed history

Changelog & Branch Updates

Tagged releases are kept separate from the continuously updated release and master branches. This page shows the three selected tagged releases, not the complete release history. Every entry below links to its GitHub release or commit source.

GitHub Releases

Recent release branch history

The latest dated entries from the release branch’s maintained history.md file.

Open release history

2026-08-21

  • Support neovim OSC 8 hyperlinks. Hold Command on macOS or Ctrl on Linux/Windows to open the link. In mouse-capturing TUI applications, also hold Shift.

2026-08-19

  • Add a provider-neutral Next Edit API with versioned candidates, cancellation, preview, navigation, acceptance, Vim/Neovim actions, and extension-owned handleDidShowNextEdit callbacks.

2026-08-15

  • Upgrade extension loader:
    • No longer modify Module.prototype._compile
    • Plugins use an enhanced console, including consoles imported via require
    • Support loading ESM-format plugins; requires the node flag --experimental-vm-modules at startup, added by default
    • Plugins use an encapsulated standalone runtime API, and extensionId is included when registering callback functions for easy tracking
  • Extension loader and loadExtension accept sourceCode with an extensionRoot to load a plugin from its complete CommonJS bundle (generated by coc-test) instead of resolving the entry through the package.json main field.

2026-08-14

  • Break Change: minimal node version changed from 20.19.0 to 22.15.0.

2026-08-15

  • Add a per-extension coc.nvim API facade: every extension runtime receives its own frozen top-level API object. Mutable core singletons (workspace, window, commands, languages, sources, services, extensions, diagnosticManager, listManager, snippetManager, events, mcp) are wrapped so extensions never receive raw manager objects; immutable value exports are shared directly and nvim stays a live getter. Mutating one extension's facade cannot affect another extension or coc core.
  • Attribute extension callback errors to the owning plugin: command handlers, event listeners and language providers registered through the facade are tagged with the extension id, so command errors are prefixed with [extension: <id>], event handler errors and slow-handler warnings include the extension id, and provider __extensionName now comes from the registration owner instead of parsing stack traces. Extension-owned registrations are disposed with the runtime.
  • Add ESM extension support to the per-extension VM loader: ESM entries and imports execute through vm.SourceTextModule inside the owning extension context, and coc.nvim, Node builtins, CommonJS modules and JSON are bridged with vm.SyntheticModule. CJS require() of ESM is rejected with ERR_REQUIRE_ESM, CJS dynamic import() of ESM works, and ESM reload creates a fresh context, caches and namespace. coc.nvim now starts Node with --experimental-vm-modules automatically.
  • Package exports resolution prefers a coc.nvim condition over require and import (Node matches exports keys in object order, so the coc-specific build wins only when checked first); nested conditions prefer node and require.
  • Migrate extension loading to a per-extension VM loader: every extension now owns its own vm.Context and module cache, CommonJS modules execute through vm.compileFunction with an extension-local synchronous require, and coc.nvim no longer patches Module.prototype._compile, wraps module sources with Module.wrap, or executes extension code with vm.runInContext().
  • Extension reload creates a fresh context and module cache: old global state disappears and entry/dependencies re-execute, while other extensions are untouched. Failed modules are removed from the cache and module graph and are re-executed on the next load.
  • require("coc.nvim") resolves to a stable per-extension API object; require("process") and require("node:process") return the sandbox process facade (the same object as the global process) with exit/kill/etc. stubbed, and mutable require.cache/require.extensions are no longer exposed to extensions.
  • Each extension now owns an independent enhanced console: timers (time/timeLog/timeEnd), counters (count/countReset), groups, dir, table, trace, assert, and clear are isolated per extension and routed through the extension logger. require("console") and require("node:console") return a per-extension facade whose top-level methods route to the extension console while the native Console class is preserved. Reload discards console state and identity; the process-global console is never modified.

2026-08-13

  • Migrate the test suite from Vitest to the Node native test runner (node:test) on Node 24. Tests no longer import Vitest globals; native test globals are injected per file, unit tests live under src/__tests__/unit with shared test utilities, and ESM compatibility shims stay local to the test bundle.
  • Rewrite the test runner as scripts/test/cli.mjs: unit tests are compiled with esbuild and run from their real .test.ts source paths, while editor tests run in per-file nvim/Neovim worker processes. The runner overlaps lanes, caches bundles and compilation, supports -t filters under isolation mode, and kills hung editor workers after a graceful timeout.
  • Run client integration tests against in-process fake servers instead of forked child processes, removing several child-process spawns and LSP handshakes (error-handler, initialize-failure, dynamic and pure RPC client tests).
  • Report test coverage from raw V8 files, including type-only coverage, and run coverage only on the stable Neovim job in CI; editor test concurrency is bounded locally and pinned on CI to keep runs deterministic.
  • Stabilize flaky editor tests: wait for echoed messages through a new Message event instead of screen scraping, attach the document before completion navigation, guard stale linked-editing provider results, and stabilize runner prompts plus completion/workspace CI tests.
  • Add the Message event to events.on(), fired when Notifications echoes a message, so tests and extensions can observe echoed output reliably.
  • Fix MCP glob variants to resolve symlink tails for directory globs such as link/**, so a glob through a symlink also matches the target path.

2026-08-10

  • Add workspace.registerInsertKeymap() for dynamic insert mappings that return ordered literal text and special keys directly, with current Vim state supplied through evaluated arglist expressions.

2026-08-07

  • Add languageserver.<name>.languageIdMap configuration which maps a filename (or absolute path) to the languageId sent in textDocument/didOpen for that server, e.g. {"application.yml": "spring-boot-properties-yaml"}. This allows a server to receive a languageId different from the buffer filetype without affecting other servers.

2026-08-05

  • MCP: the coc-mcp bridge connects to the first coc.nvim instance whose workspace contains the bridge working directory and exits when no matching instance is found. --match-first connects to the first available instance regardless of the working directory.
  • MCP: the coc-mcp bridge fails immediately with a "coc.nvim MCP service not found" error when no usable connection exists at startup. Start vim/nvim with "mcp.autoStart": true before launching Codex.
  • MCP: the socket server keeps running across :CocRestart — its started state is kept in a vim variable and restored on startup, the per-instance discovery file is keyed by the vim pid, and the coc-mcp bridge reconnects to the new endpoint/token when the file is rewritten.
  • MCP: mcp.autoStart controls whether the socket server starts automatically with coc.nvim (default off); :CocCommand mcp.start starts it on demand for the current session regardless of the setting.
  • MCP: the coc-mcp bridge reads the private key from COC_MCP_AUTH_KEY_FILE (path to a PEM file).
  • MCP: new editor/state tool returns a snapshot of the active editor — workspace root, active document (uri, language, version), cursor, visual selection, visible line range, surrounding lines, innermost document symbol under the cursor and current diagnostics.
  • MCP: cache idempotent LSP queries (lsp/hover, lsp/definition, lsp/references and the other read-only batch queries) keyed by document uri, position, method and document version with a short TTL, and invalidate the cache when the document changes, cutting latency for repeated agent queries on the same symbol.
  • MCP: LSP queries abandoned by a tool timeout or notifications/cancelled are dropped from the per-server request queue, and requests the language server never answered are tracked as stuck; once all request slots are stuck, new queries to that server fail fast with a restart hint. The same bound applies with mcp.maxConcurrentRequests: 0 (unlimited concurrency, 16 stuck requests per server).
  • MCP: workspace/apply_edit saves all modified buffers with :wa after applying, so edits are on disk for subsequent tools; the result reports saved and a saveError when the save fails.
  • MCP: new mcp.allowedTools whitelist controls which tools are exposed to agents — tools/list only returns whitelisted names and tools/call rejects the rest. Default is empty (no tools exposed) so tool access is opt-in; the configuration documents the full built-in tool list.
  • MCP: the mcp.logLevel configuration is not supported.
  • MCP: protocol version negotiation supports 2024-11-05 in addition to 2025-06-18 and 2025-11-25: sessions on 2024-11-05 get tools/list entries limited to name/description/inputSchema and tools/call results without structuredContent, matching the 2024-11-05 schema.

2026-08-04

  • Add configuration suggest.pumAlign to align the popup menu with a field ("abbr", "menu", "kind" or "shortcut") instead of the first text.
  • Advertise LSP 3.18 client capabilities for code lens and signature help:
    • textDocument.codeLens.resolveSupport now reports the properties the client can resolve lazily (the code lens command).
    • textDocument.signatureHelp.noActiveParameterSupport now reports that activeParameter can be null to indicate no active parameter; the signature float no longer highlights the first parameter in that case.
  • Code lens action picker and code action menus now show Command#tooltip as a title - tooltip suffix when the server provides one.
  • Add multi-range formatting API for LSP 3.18 textDocument/rangesFormatting: DocumentRangeFormattingEditProvider gains an optional provideDocumentRangesFormattingEdits method and languages exposes provideDocumentRangesFormattingEdits, falling back to per-range formatting when the provider has no ranges support. The client capability textDocument.rangeFormatting.rangesSupport is advertised to servers. Existing visual block selection formatting behavior is unchanged.
  • Support LSP 3.18 CompletionList.applyKind: the client now advertises completionList.applyKindSupport and data in itemDefaults, and honors applyKind merge/replace rules for commitCharacters (union) and data (shallow merge, falling back to the default value when the item has none).
  • Add a built-in MCP (Model Context Protocol) server so agents like Codex can interact with the running editor through tools, notifications and resources:
    • :CocCommand mcp.start starts a loopback socket server (TCP or Unix) tools to read editor buffers (including unsaved changes), search the workspace, apply workspace edits, and query the language servers; bin/coc-mcp.js (command coc-mcp) is a stdio bridge for Codex.
    • New public API mcp.registerTool() lets extensions register custom MCP tools.
    • New configuration section mcp.* (enabled, host, port, transport, authRequired, authClientPublicKey, allowedPaths, deniedPaths, maxClients, frameMaxBytes, timeout, readTimeout, idleTimeout, maxRequestsPerSecond, maxConcurrentRequests, languageServiceMap) and commands :CocCommand mcp.start, mcp.stop and mcp.status.
    • Protocol: MCP 2025-06-18 with 2025-11-25 version negotiation, coc/* notifications (document saved/changed, diagnostics, workspace folders, editor state, service state) via coc/subscribe, and coc:// resources. Interface specification and roadmap live in the MCP design document, usage guide in doc/coc-mcp.txt.
    • :CocInfo includes an ## MCP server section (transport, address, pid, cwd and connected clients with pid and connect/last-activity time); the MCP service closes its discovery/socket files on SIGTERM/SIGINT and on Vim 8 VimLeavePre, and clients (the stdio bridge) exit cleanly when the service shuts down.
    • MCP discovery is unified under ~/.coc/mcp : every coc.nvim instance writes coc-<pid>.json (and its unix socket) there, stale files are cleaned by the stdio bridge on every scan, and the bridge reads the same directory without any environment variable (COC_MCP_DIR is an optional override).
    • LSP list tools cap their results via an optional maxResults argument (defaults: 200 for location tools, 500 for symbol tools, 100 for diagnostics and code actions; hard maximum 1000). Truncated responses add returned and truncated to the structured output next to the total count, and location tools truncate before enriching lineText.

Snapshot refreshed

Current branch snapshots

These commits are newer than the latest tagged release and are not release notes.

Loaded from SQLite

Release branch snapshot

Commit

Commit 95073dab304d

Source commit 95073dab30
Database-backed synchronization snapshot

Synchronized source commit

Commit

Commit 555f5cec3ddd

Source commit 555f5cec3d
Database-backed synchronization snapshot

Selected tagged releases

Release notes are loaded separately after the page is ready. For the complete release history, use the GitHub Releases link above.

Loading selected tagged releases…