{"id":13872482,"url":"https://github.com/neovim/node-client","last_synced_at":"2025-05-14T00:10:32.933Z","repository":{"id":27181419,"uuid":"30651283","full_name":"neovim/node-client","owner":"neovim","description":"Nvim Node.js client and plugin host","archived":false,"fork":false,"pushed_at":"2025-02-24T06:33:19.000Z","size":3877,"stargazers_count":510,"open_issues_count":23,"forks_count":50,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-04-27T00:31:56.303Z","etag":null,"topics":["neovim","nodejs","nvim","rpc","typescript","vim"],"latest_commit_sha":null,"homepage":"https://neovim.io/node-client/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/neovim.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-MIT","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-02-11T14:23:57.000Z","updated_at":"2025-04-14T17:47:39.000Z","dependencies_parsed_at":"2023-10-16T03:29:22.785Z","dependency_job_id":"63f1378d-39da-4f3d-bc55-f95b3bb0fe9c","html_url":"https://github.com/neovim/node-client","commit_stats":{"total_commits":605,"total_committers":37,"mean_commits":16.35135135135135,"dds":0.7388429752066116,"last_synced_commit":"74880148636620f3f76e0a568aed10ce18b512a1"},"previous_names":[],"tags_count":53,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neovim%2Fnode-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neovim%2Fnode-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neovim%2Fnode-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neovim%2Fnode-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/neovim","download_url":"https://codeload.github.com/neovim/node-client/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252663893,"owners_count":21784827,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["neovim","nodejs","nvim","rpc","typescript","vim"],"created_at":"2024-08-05T23:00:44.404Z","updated_at":"2025-05-14T00:10:32.892Z","avatar_url":"https://github.com/neovim.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# Neovim node.js client\n\n| CI (node \u003e= 14, Linux/macOS/Windows)                                                                                                              | Coverage                               | npm                             |\n| ------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ------------------------------- |\n| [![ci](https://github.com/neovim/node-client/actions/workflows/ci.yml/badge.svg)](https://github.com/neovim/node-client/actions/workflows/ci.yml) | [![Coverage Badge][]][Coverage Report] | [![npm version][]][npm package] |\n\n## Install\n\nFor \"remote plugins\", the Nvim [Node.js provider](https://neovim.io/doc/user/provider.html#provider-nodejs) expects the `neovim` package to be globally installed:\n\n```bash\nnpm install -g neovim\n```\n\nOr for non-plugin purposes, `neovim` works like any other NPM package.\nSee below for a quickstart example that you can copy and run immediately.\n\n## Usage\n\n### Functions\n\nThe `neovim` package provides these functions:\n\n- `attach()`: The primary interface. Takes a process, socket, or pair of write/read streams and returns a `NeovimClient` connected to an `nvim` process.\n- `findNvim()`: Tries to find a usable `nvim` binary on the current system.\n\n### Logging\n\n- At load-time, the `neovim` module replaces (\"monkey patches\") `console` with its `logger`\n  interface, so `console.log` will call `logger.info` instead of writing to stdout (which would\n  break the stdio RPC channel).\n  - To skip this patching of `console.log`, pass a custom `logger` to `attach()`.\n  - Best practice in any case is to use the `logger` available from the `NeovimClient` returned by\n    `attach()`, instead of `console` logging functions.\n- Set the `$NVIM_NODE_LOG_FILE` env var to (also) write logs to a file.\n- Set the `$ALLOW_CONSOLE` env var to (also) write logs to stdout. **This will break any (stdio) RPC\n  channel** because logs written to stdout are invalid RPC messages.\n\n### Quickstart: connect to Nvim\n\nFollowing is a complete, working example.\n\n1. Install the `neovim` package _locally_ in any directory (i.e. without `-g`. Node throws `ERR_MODULE_NOT_FOUND` if a script imports a _globally_ installed package).\n   ```bash\n   npm install neovim\n   ```\n2. Paste the script below into a `demo.mjs` file and run it!\n\n   ```\n   ALLOW_CONSOLE=1 node demo.mjs\n   ```\n\n   - `$ALLOW_CONSOLE` env var must be set, because logs are normally not printed to stdout.\n     - Note: `$ALLOW_CONSOLE` is only for demo purposes. It cannot be used for remote plugins or\n       whenever stdio is an RPC channel, because writing logs to stdout would break the RPC\n       channel.\n   - Script:\n\n   ```js\n   import * as child_process from 'node:child_process';\n   import * as assert from 'node:assert';\n   import { attach, findNvim } from 'neovim';\n\n   // Find `nvim` on the system and open a channel to it.\n   (async function () {\n     const found = findNvim({ orderBy: 'desc', minVersion: '0.9.0' });\n     console.log(found);\n     const nvim_proc = child_process.spawn(found.matches[0].path, ['--clean', '--embed'], {});\n     const nvim = attach({ proc: nvim_proc });\n\n     nvim.command('vsp | vsp | vsp');\n\n     const windows = await nvim.windows;\n     assert.deepStrictEqual(windows.length, 4);\n     assert.ok(windows[0] instanceof nvim.Window);\n\n     nvim.window = windows[2];\n     const win = await nvim.window;\n     assert.ok(win.id !== windows[0].id);\n     assert.deepStrictEqual(win.id, windows[2].id);\n\n     const buf = await nvim.buffer;\n     assert.ok(buf instanceof nvim.Buffer);\n     const lines = await buf.lines;\n     assert.deepStrictEqual(lines, []);\n\n     await buf.replace(['line1', 'line2'], 0);\n     const newLines = await buf.lines;\n     assert.deepStrictEqual(newLines, ['line1', 'line2']);\n\n     if (nvim_proc.disconnect) {\n       nvim_proc.disconnect();\n     }\n     nvim.quit();\n     while (nvim_proc.exitCode === null) {\n       await new Promise(resolve =\u003e setTimeout(resolve, 100));\n       console.log('waiting for Nvim (pid %d) to exit', nvim_proc.pid);\n     }\n     console.log('Nvim exit code: %d', nvim_proc.exitCode);\n   })();\n   ```\n\n### Create a remote plugin\n\nNeovim supports [remote plugins](https://neovim.io/doc/user/remote_plugin.html), which are plugins implemented as Nvim API clients.\nThis package contains both the \"API client\" (which talks to nvim) and \"remote plugin host\" (which discovers and runs Nvim node.js remote plugins).\n\nYou can define a remote plugin as a file or folder in an `rplugin/node/` directory on Nvim's ['runtimepath'](https://neovim.io/doc/user/options.html#'runtimepath').\nIf the plugin is a folder, the `main` script from `package.json` will be loaded.\n\nThe plugin must export a function which takes a `NvimPlugin` object as its only parameter. You may then register autocmds, commands and functions by calling methods on the `NvimPlugin` object.\n**Avoid heavy initialisation or async functions at this stage,** because Nvim may only be collecting information about your plugin without wishing to actually use it.\nInstead, wait for one of your autocmds, commands or functions to be called before starting any processing.\n\n### Remote plugin examples\n\nSee [`examples/`](https://github.com/neovim/node-client/tree/master/examples) for remote plugin examples.\n\n### Remote plugin API\n\n```ts\nNvimPlugin.nvim;\n```\n\nThis is the nvim api object you can use to send commands from your plugin to nvim.\n\n```ts\n  NvimPlugin.setOptions(options: NvimPluginOptions);\n\n  interface NvimPluginOptions {\n    dev?: boolean;\n    alwaysInit?: boolean;\n  }\n```\n\nSet your plugin to dev mode, which will cause the module to be reloaded on each invocation.\n`alwaysInit` will always attempt to attempt to re-instantiate the plugin. e.g. your plugin class will\nalways get called on each invocation of your plugin's command.\n\n```ts\n  NvimPlugin.registerAutocmd(name: string, fn: Function, options: AutocmdOptions): void;\n  NvimPlugin.registerAutocmd(name: string, fn: [any, Function], options: AutocmdOptions): void;\n\n  interface AutocmdOptions {\n    pattern: string;  // See `:help autocmd-pattern`.\n    eval?: string;    // Vimscript expression evaluated by the Nvim peer.\n    sync?: boolean;   // Force blocking (non-async) behavior.\n  }\n```\n\nRegisters an autocmd for the event `name`, calling your function `fn` with `options`. Pattern is the only required option. If you wish to call a method on an object you may pass `fn` as an array of `[object, object.method]`.\n\nBy default autocmds, commands and functions are all treated as asynchronous and should return `Promises` (or should be `async` functions).\n\n```ts\n  NvimPlugin.registerCommand(name: string, fn: Function, options?: CommandOptions): void;\n  NvimPlugin.registerCommand(name: string, fn: [any, Function], options?: CommandOptions): void;\n\n  interface CommandOptions {\n    sync?: boolean;   // Force blocking (non-async) behavior.\n    range?: string;   // See `:help :range`.\n    nargs?: string;   // See `:help :command-nargs`.\n  }\n```\n\nRegisters a command named by `name`, calling function `fn` with `options`. This will be invoked from nvim by entering `:name` in normal mode.\n\n```ts\n  NvimPlugin.registerFunction(name: string, fn: Function, options?: NvimFunctionOptions): void;\n  NvimPlugin.registerFunction(name: string, fn: [any, Function], options?: NvimFunctionOptions): void;\n\n  interface NvimFunctionOptions {\n    sync?: boolean;   // Force blocking (non-async) behavior.\n    range?: string;   // See `:help :range`.\n    eval?: string;    // Vimscript expression evaluated by the Nvim peer.\n  }\n```\n\nRegisters a function with name `name`, calling function `fn` with `options`. This will be invoked from nvim by entering eg `:call name()` in normal mode.\n\n## Debug / troubleshoot\n\nFor debugging and configuring logging, you can set the following environment variables which are used by the `neovim` package (or `nvim` itself where noted):\n\n- `NVIM_NODE_HOST_DEBUG`: Spawns the node process that calls `neovim-client-host` with `--inspect-brk` so you can have a debugger.\n  Pair that with this [Node Inspector Manager Chrome plugin](https://chrome.google.com/webstore/detail/nodejs-v8-inspector-manag/gnhhdgbaldcilmgcpfddgdbkhjohddkj?hl=en)\n- Logging: Logging is done using `winston` through the `logger` module. This package replaces `console` with this interface.\n  - `NVIM_NODE_LOG_LEVEL`: Sets the logging level for winston. Default is `debug`.\n    Available levels: `{ error: 0, warn: 1, info: 2, verbose: 3, debug: 4, silly: 5 }`\n  - `NVIM_NODE_LOG_FILE`: Sets the log file path.\n- Usage through node REPL\n  - `NVIM_LISTEN_ADDRESS`:\n    1. Start Nvim with a known address (or use the $NVIM_LISTEN_ADDRESS of a running instance):\n       ```\n       $ NVIM_LISTEN_ADDRESS=/tmp/nvim nvim\n       ```\n    2. In another terminal, connect a node REPL to Nvim\n       ```javascript\n       // `scripts/nvim` will detect if `NVIM_LISTEN_ADDRESS` is set and use that unix socket\n       // Otherwise will create an embedded `nvim` instance\n       require('neovim/scripts/nvim').then(nvim =\u003e {\n         nvim.command('vsp');\n       });\n       ```\n\nSee the tests and [`scripts`](https://github.com/neovim/node-client/tree/master/packages/neovim/scripts) for more examples.\n\n## Develop\n\nAfter cloning the repo, run `npm install` to install dev dependencies. The main `neovim` library is in `packages/neovim`.\n\n### Run tests\n\n    npm run build \u0026\u0026 NVIM_NODE_LOG_FILE=log npm run test\n\n## Maintain\n\n### Release\n\nOnly maintainers of the [neovim NPM package](https://www.npmjs.com/package/neovim) can publish a release. Follow these steps to publish a release:\n\n1. Update `CHANGELOG.md`.\n2. Update version. Build and publish the package. Tag the release and push.\n   ```bash\n   # Choose major/minor/patch as needed.\n   npm version --no-git-tag-version patch\n   npm version -w packages/neovim/ patch\n   git add package*.json packages/neovim/package.json\n   git commit -m 'release'\n   # Note: this copies the top-level README.md/CHANGELOG.md to packages/neovim/.\n   npm run publish:neovim\n   export _VERSION=$(grep -o 'version\": \"[^\"]\\+' packages/neovim/package.json | sed 's/.*\"//')\n   git tag \"v${_VERSION}\"\n   git push --tags\n   git push\n   ```\n3. Post-release tasks:\n   - Add stub to `CHANGELOG.md`.\n   - Bump and commit.\n     ```bash\n     npm version --no-git-tag-version prerelease --preid dev\n     npm version -w packages/neovim/ --no-git-tag-version prerelease --preid dev\n     git add package*.json packages/neovim/package.json\n     git commit -m bump\n     git push\n     ```\n\n### Regenerate documentation website\n\nThe docs website is currently not automated. Follow these steps to regenerate it:\n\n```bash\nnpm run doc -w packages/neovim\ngit checkout gh-pages\nshopt -s extglob\ngit rm -r !(node_modules|packages)\nmv packages/neovim/doc/* .\nrm -r packages/\ngit add !(node_modules|packages)\ngit commit -m 'publish docs'\ngit push origin HEAD:gh-pages\n```\n\n## Contributors\n\n- [@billyvg](https://github.com/billyvg) for rewrite\n- [@mhartington](https://github.com/mhartington) for TypeScript rewrite\n- [@fritzy](https://github.com/fritzy) for transferring over the npm package repo `neovim`!\n- [@rhysd](https://github.com/rhysd), [@tarruda](https://github.com/tarruda), [@nhynes](https://github.com/nhynes) on work for the original `node-client`\n- [@justinmk](https://github.com/justinmk) Neovim maintainer\n\n[Coverage Badge]: https://codecov.io/gh/neovim/node-client/branch/master/graph/badge.svg\n[Coverage Report]: https://codecov.io/gh/neovim/node-client\n[npm version]: https://img.shields.io/npm/v/neovim.svg\n[npm package]: https://www.npmjs.com/package/neovim\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneovim%2Fnode-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneovim%2Fnode-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneovim%2Fnode-client/lists"}