npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

opencode-nvim-editor-context

v0.1.0

Published

Neovim editor context awareness for OpenCode agents

Readme

opencode-nvim-editor-context

An OpenCode plugin that gives the AI agent awareness of your current Neovim editor state — what file you have open, where your cursor is, what text you have selected, and any diagnostics (errors/warnings). When you say "explain this" or "fix this", the agent knows what "this" is.

How it works

The plugin connects OpenCode to a running Neovim instance via its built-in RPC socket. When the agent needs to know what you're looking at, it queries Neovim for the current editor state and gets back a JSON response.

┌──────────────────────────────┬─────────────────────────────────┐
│                              │                                 │
│  Neovim                      │  OpenCode                       │
│                              │                                 │
│  cursor at line 42           │  User: "Why does this function  │
│  ▌                           │   return null sometimes?"       │
│  function foo(items) {       │                                 │
│  ~~~~~~~~ selected ~~~~~~~~  │  Agent: "The function at line   │
│                              │   42 can return null when the   │
│                              │   `items` array is empty — the  │
│                              │   early return on line 44 exits │
│                              │   before reaching the reduce."  │
│                              │                                 │
└──────────────────────────────┴─────────────────────────────────┘

The agent can see:

  • Current file — absolute path of the open buffer
  • Cursor position — line and column (1-indexed)
  • Visual selection — start/end positions and the selected text
  • Diagnostics — LSP errors, warnings, and hints for the current buffer

Components

The plugin has two parts that are installed separately:

1. Neovim plugin (lua/editor-context/)

A Lua module that registers a global EditorContext() function. This function gathers the current editor state and returns it as JSON. It's queryable via Neovim's RPC socket from outside the editor.

2. OpenCode plugin (opencode-plugin/index.ts)

An OpenCode plugin that registers an editor_context tool. When the agent calls it, the tool queries Neovim's EditorContext() function via the RPC socket and returns the result.

Dependencies

Installation

1. Neovim plugin

Using lazy.nvim:

{
  "talldan/opencode-nvim-editor-context",
  config = function()
    require("editor-context").setup()
  end,
}

2. OpenCode plugin

Add the plugin to your opencode.json configuration:

{
  "plugin": ["opencode-nvim-editor-context"]
}

This can go in your global config (~/.config/opencode/opencode.json) or a project-level config (opencode.json in your project root).

Restart OpenCode to load the plugin. The editor_context tool will be available to the AI agent automatically.

3. Neovim RPC socket

The tool communicates with Neovim via its RPC socket. In most cases, no configuration is needed — the tool auto-discovers running Neovim instances.

Auto-discovery (default)

The tool automatically finds Neovim by:

  1. Checking the NVIM_SOCKET environment variable (if set, always used)
  2. Scanning for Neovim sockets in standard locations ($TMPDIR and /tmp)
  3. Preferring the Neovim instance whose working directory matches the current project
  4. Falling back to the first live Neovim instance found

This means if you just run nvim in your project directory, OpenCode will find it automatically.

Explicit configuration (optional)

If auto-discovery doesn't work for your setup (e.g., multiple Neovim instances in the same directory), you can set the socket path explicitly:

export NVIM_SOCKET=/tmp/nvim.sock
nvim --listen $NVIM_SOCKET

Make sure NVIM_SOCKET is set in the environment where OpenCode runs.

If you use CMUX, you can set this in your workspace configuration so both Neovim and OpenCode share the socket path automatically.

Example

Say you have a file open in Neovim with your cursor on a function, and you ask the agent "why does this return null sometimes?" The agent calls the editor_context tool and gets back:

{
  "file": "/Users/you/project/src/utils.ts",
  "cursor": { "line": 42, "col": 5 },
  "selection": {
    "start_line": 42,
    "start_col": 1,
    "end_line": 48,
    "end_col": 2,
    "text": "function foo(items: string[]) {\n  if (!items.length) {\n    return null;\n  }\n  return items.reduce((acc, item) => acc + item.length, 0);\n}"
  },
  "diagnostics": [
    { "line": 43, "col": 5, "severity": "WARN", "source": "typescript", "message": "Type 'null' is not assignable to type 'number'" }
  ]
}

The agent now knows exactly what code you're looking at, what text you selected, and that there's a type warning on the early return. It can answer your question directly without needing to read the file or guess what you meant by "this".

Design

Architecture

OpenCode (agent)                    Neovim (editor)
     │                                   │
     │  nvim --headless --server         │
     │    $NVIM_SOCKET --remote-expr     │
     │    "luaeval('EditorContext()')"    │
     │ ─────────────────────────────────>│
     │                                   │
     │  JSON { file, cursor,             │
     │    selection, diagnostics }       │
     │ <─────────────────────────────────│
     │                                   │

The tool uses Neovim's --remote-expr to evaluate a Lua expression on the running Neovim instance. This is a standard Neovim feature that works in any terminal — no CMUX or specific terminal emulator required.

Key design decisions:

  • --headless flag on remote calls: Prevents Neovim from emitting terminal escape sequences when invoked from a subprocess (e.g., Bun's shell). Without this, the JSON response gets polluted with control codes.
  • Global EditorContext() function: Registered as a global (not module-scoped) so it can be called via luaeval() without needing the module require path.
  • Selection handling: Supports both active visual mode selections (using getpos("v") and getpos(".")) and the last visual selection marks ('< and '>). This means the agent can see what you selected even after you leave visual mode.
  • 1-indexed positions: All line and column numbers are 1-indexed to match what users see in the editor, even though Neovim's API is 0-indexed internally.
  • Socket auto-discovery: When NVIM_SOCKET is not set, the tool scans $TMPDIR/nvim.$USER/ and /tmp for Neovim socket files, verifies each is live, and uses lsof to match the Neovim process's working directory against the current project. This allows zero-configuration usage — just run nvim and OpenCode will find it.

Future improvements

File content inclusion

Optionally include a window of lines around the cursor (e.g., 20 lines above and below) so the agent has immediate context without needing to read the file separately.

Multiple buffer awareness

Report on all open buffers, not just the current one. This would let the agent understand which files the user is working across.

Change tracking

Track unsaved modifications in the buffer compared to the file on disk. The agent could see what the user has been editing without needing git diff.