Functions for locating Neovim executables on the system and establishing connections to Neovim instances through various transport mechanisms.
Establishes a connection to a Neovim instance via streams, child process, or socket.
/**
* Attaches to a Neovim instance using the specified transport method.
* Returns a NeovimClient instance for interacting with Neovim.
*
* @param options - Connection options specifying transport method
* @returns NeovimClient instance connected to Neovim
*/
function attach(options: Attach): NeovimClient;
interface Attach {
/** Input stream for reading from Neovim */
reader?: NodeJS.ReadableStream;
/** Output stream for writing to Neovim */
writer?: NodeJS.WritableStream;
/** Child process with stdin/stdout connected to Neovim */
proc?: NodeJS.Process | child_process.ChildProcess;
/** Unix socket or Windows named pipe path */
socket?: string;
/** Optional configuration */
options?: {
/** Custom logger instance (prevents console monkey-patching) */
logger?: any;
};
}Usage Examples:
import * as child_process from 'node:child_process';
import * as net from 'node:net';
import { attach } from 'neovim';
// Attach via child process (most common)
const nvim_proc = child_process.spawn('nvim', ['--embed'], {});
const nvim1 = attach({ proc: nvim_proc });
// Attach via Unix socket
const nvim2 = attach({ socket: '/tmp/nvim.sock' });
// Attach via Windows named pipe
const nvim3 = attach({ socket: '\\\\.\\pipe\\nvim-pipe' });
// Attach via streams
const socket = net.createConnection({ path: '/tmp/nvim.sock' });
const nvim4 = attach({
reader: socket,
writer: socket
});
// Attach with custom logger
const customLogger = {
level: 'info',
info: (msg: string) => { /* ... */ },
warn: (msg: string) => { /* ... */ },
error: (msg: string) => { /* ... */ },
debug: (msg: string) => { /* ... */ }
};
const nvim5 = attach({
proc: nvim_proc,
options: { logger: customLogger }
});
// Use NeovimClient
await nvim1.command('echo "Hello from Node.js!"');
const buf = await nvim1.buffer;
await buf.append(['Line 1', 'Line 2']);
// Clean up
nvim1.quit();Searches for Neovim executables on the system and validates their versions.
/**
* Searches for Neovim executable on the system.
* Checks common installation locations and validates versions.
*
* @param opt - Search options
* @returns Result containing valid and invalid matches
*/
function findNvim(opt?: FindNvimOptions): Readonly<FindNvimResult>;
interface FindNvimOptions {
/** Minimum required Neovim version (inclusive, semver format) */
minVersion?: string;
/** Sort order for results: 'desc' (newest first, default) or 'none' */
orderBy?: 'desc' | 'none';
/** Stop searching after first valid match */
firstMatch?: boolean;
/** Specific file paths to check first (before searching directories) */
paths?: string[];
/** Additional directories to search beyond default locations */
dirs?: string[];
}
interface FindNvimResult {
/** Valid Neovim executables that meet criteria */
matches: ReadonlyArray<NvimVersion>;
/** Invalid or failed executables */
invalid: ReadonlyArray<NvimVersion>;
}
interface NvimVersion {
/** Absolute path to nvim executable */
path: string;
/** Neovim version string (e.g., '0.9.4') if valid */
nvimVersion?: string;
/** Build type (e.g., 'Release', 'Debug') if valid */
buildType?: string;
/** LuaJIT version if valid */
luaJitVersion?: string;
/** Error object if validation failed */
error?: Readonly<Error>;
}Usage Examples:
import { findNvim } from 'neovim';
// Find any Neovim executable
const result1 = findNvim();
if (result1.matches.length > 0) {
console.log('Found Neovim at:', result1.matches[0].path);
console.log('Version:', result1.matches[0].nvimVersion);
}
// Find Neovim with minimum version
const result2 = findNvim({ minVersion: '0.9.0' });
if (result2.matches.length === 0) {
throw new Error('Neovim 0.9.0 or higher not found');
}
// Get newest version only
const result3 = findNvim({
minVersion: '0.8.0',
orderBy: 'desc',
firstMatch: true
});
const newestNvim = result3.matches[0];
// Search specific paths first
const result4 = findNvim({
paths: ['/usr/local/bin/nvim', '/opt/nvim/bin/nvim'],
minVersion: '0.9.0'
});
// Search additional directories
const result5 = findNvim({
dirs: ['/home/user/custom-nvim/bin', '/opt/applications'],
minVersion: '0.10.0'
});
// Handle invalid installations
const result6 = findNvim();
console.log('Valid installations:', result6.matches.length);
console.log('Invalid installations:', result6.invalid.length);
for (const invalid of result6.invalid) {
console.log(`Failed to validate ${invalid.path}:`, invalid.error?.message);
}
// Use with spawn
import * as child_process from 'node:child_process';
import { attach } from 'neovim';
const found = findNvim({ minVersion: '0.9.0', orderBy: 'desc' });
if (found.matches.length === 0) {
throw new Error('Compatible Neovim not found');
}
const nvimPath = found.matches[0].path;
const nvim_proc = child_process.spawn(nvimPath, ['--embed', '--clean'], {});
const nvim = attach({ proc: nvim_proc });
await nvim.command('echo "Using Neovim ' + found.matches[0].nvimVersion + '"');Connect to an already-running Neovim instance using $NVIM_LISTEN_ADDRESS:
import { attach } from 'neovim';
// Neovim running with: NVIM_LISTEN_ADDRESS=/tmp/nvim nvim
const nvim = attach({ socket: process.env.NVIM_LISTEN_ADDRESS || '/tmp/nvim' });
// Now you can control the running instance
await nvim.command('vsp');
const buffers = await nvim.buffers;Spawn a new Neovim instance as a child process:
import * as child_process from 'node:child_process';
import { attach, findNvim } from 'neovim';
// Find Neovim
const found = findNvim({ minVersion: '0.9.0' });
const nvimPath = found.matches[0].path;
// Spawn with options
const nvim_proc = child_process.spawn(nvimPath, [
'--embed', // Enable msgpack-rpc
'--clean', // Skip config files
'--headless', // No UI (optional)
'-u', 'NONE', // No vimrc (optional)
], {
env: { ...process.env, NVIM_LOG_FILE: '/tmp/nvim.log' }
});
const nvim = attach({ proc: nvim_proc });
// Handle process events
nvim_proc.on('exit', (code) => {
console.log('Neovim exited with code:', code);
});
nvim_proc.on('error', (err) => {
console.error('Process error:', err);
});Properly close connections to Neovim:
import { attach } from 'neovim';
const nvim = attach({ proc: nvim_proc });
// Option 1: Call quit() to exit Neovim
nvim.quit();
// Option 2: Close client connection
await nvim.close();
// Option 3: Use async disposal (Node.js 20+)
{
await using nvim = attach({ proc: nvim_proc });
// Use nvim...
} // Automatically disposed
// Wait for process to exit
nvim_proc.on('exit', () => {
console.log('Neovim process ended');
});Most common method - spawn Neovim as child process:
import * as child_process from 'node:child_process';
import { attach } from 'neovim';
const nvim_proc = child_process.spawn('nvim', ['--embed']);
const nvim = attach({ proc: nvim_proc });Pros:
Cons:
Connect to existing Neovim instance via socket:
import { attach } from 'neovim';
// Unix socket (Linux/macOS)
const nvim1 = attach({ socket: '/tmp/nvim.sock' });
// Named pipe (Windows)
const nvim2 = attach({ socket: '\\\\.\\pipe\\nvim-pipe' });Pros:
Cons:
Starting Neovim with socket:
# Unix
$ NVIM_LISTEN_ADDRESS=/tmp/nvim.sock nvim
# Or explicitly
$ nvim --listen /tmp/nvim.sockUse custom read/write streams:
import * as net from 'node:net';
import { attach } from 'neovim';
const socket = net.createConnection({ path: '/tmp/nvim.sock' });
const nvim = attach({
reader: socket,
writer: socket
});
// Or use separate streams
const nvim2 = attach({
reader: process.stdin,
writer: process.stdout
});Pros:
Cons:
import { attach, findNvim } from 'neovim';
import * as child_process from 'node:child_process';
try {
// Find Neovim
const found = findNvim({ minVersion: '0.9.0' });
if (found.matches.length === 0) {
throw new Error('Neovim 0.9.0+ not found on system');
}
// Spawn and attach
const nvimPath = found.matches[0].path;
const nvim_proc = child_process.spawn(nvimPath, ['--embed']);
nvim_proc.on('error', (err) => {
console.error('Failed to spawn Neovim:', err);
});
const nvim = attach({ proc: nvim_proc });
// Handle RPC errors
try {
await nvim.command('invalid command');
} catch (err) {
console.error('Command failed:', err);
}
// Always clean up
nvim.quit();
} catch (err) {
console.error('Setup failed:', err);
}NVIM_LISTEN_ADDRESS - Socket path for connecting to existing instanceNVIM_NODE_LOG_FILE - Path to log fileNVIM_NODE_LOG_LEVEL - Log level (error, warn, info, verbose, debug, silly)ALLOW_CONSOLE - Enable console output (breaks stdio RPC, use only for debugging)console by default - pass a custom logger to avoid thisneovim package to be installed globally--listen or NVIM_LISTEN_ADDRESSfindNvim() to avoid hardcoding paths and support multiple installationsNeovimClient class returned by attach() extends Neovim with connection management methods