Registry / devops / ssh-config

ssh-config

JSON →
library0.1.6jsnpmunverified

The `ssh-config` library offers robust parsing and stringification capabilities for SSH configuration files, typically located at `~/.ssh/config`. As of its current stable version, 5.1.0, it enables developers to programmatically read, modify, and write SSH configurations while diligently preserving original formatting, comments, and whitespace. The project maintains an active release cadence, frequently addressing bugs and introducing features, such as Deno support in v5.1.0 and continuous improvements to TypeScript typings. Its primary differentiator lies in its ability to parse an SSH config into an Abstract Syntax Tree (AST)-like structure for easy manipulation and then reliably serialize it back into a valid SSH config string, ensuring changes are applied correctly without data loss. Additionally, it provides convenient helper methods like `compute` to derive the effective configuration for a specific host, and `find` for targeted section modification, offering granular control over SSH settings.

npm install ssh-config
INSTALL
IMPORT
SIG · SSH-CONFIG
S
ssh-config
devopsjavascriptv0.1.6
Install
Import
Disk
Pass rate
0/ 6
Env Coverage0 / 6
glibc
1822
musl
1822
Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
node 18226 runs
build_error
glibc
node 18226 runs
build_error
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

SSHConfig
import SSHConfig from 'ssh-config'
const SSHConfig = require('ssh-config')
While CommonJS `require` works, ESM `import` is the recommended modern approach, especially with Deno support.
parse
import SSHConfig from 'ssh-config'; SSHConfig.parse(configString)
import { parse } from 'ssh-config'
`parse` is a method of the default exported `SSHConfig` object, not a named export itself.
LineType
import { LineType } from 'ssh-config'
Available as a named export since v5.1.0 for finer-grained AST manipulation.

This quickstart demonstrates parsing an SSH config string, modifying an existing host entry, adding a new host, computing effective parameters for a host, and finally stringifying the updated configuration.

import SSHConfig from 'ssh-config'; import * as fs from 'fs'; import * as path from 'path'; const configContent = ` # This is a comment IdentityFile ~/.ssh/id_rsa Host devserver HostName 192.168.1.100 User admin Host * User keanu ForwardAgent true `; // Parse the SSH config string const config = SSHConfig.parse(configContent); // Find and modify a specific host section const devserverSection = config.find({ Host: 'devserver' }); if (devserverSection && devserverSection.config) { for (const line of devserverSection.config) { if (line.param === 'HostName') { line.value = 'dev.example.com'; break; } } } // Add a new host section config.add({ Host: 'staging', config: [ { param: 'HostName', value: 'staging.example.com' }, { param: 'User', value: 'deploy' } ] }); // Compute the effective configuration for a host const computedConfig = config.compute('staging', { ignoreCase: true }); console.log('Computed config for staging:', computedConfig); // Stringify the modified configuration back to a string const newConfigString = SSHConfig.stringify(config); console.log('\n--- Modified SSH Config ---\n'); console.log(newConfigString); // Example: writing to a temporary file (ensure directory exists) const tempDir = path.join(process.cwd(), 'temp'); if (!fs.existsSync(tempDir)) { fs.mkdirSync(tempDir); } const tempConfigFile = path.join(tempDir, 'ssh_config_modified.tmp'); fs.writeFileSync(tempConfigFile, newConfigString); console.log(`\nModified config written to: ${tempConfigFile}`);
Debug
Known issues
breakingVersion 5.0.0 introduced a breaking change in how quotation marks are reserved when handling multiple values within a configuration directive. Previously, quotation marks might have been stripped or normalized, but now they are preserved in the AST.
fix
Review any code that programmatically modifies or expects specific formatting of values with quotation marks. Adjust parsing or stringification logic if relying on previous behavior.
affects: >=5.0.0
gotchaThe `.compute()` method, by default, preserves the original casing of SSH directive names (e.g., `hOsTnaME`). OpenSSH itself treats directives case-insensitively. To ensure directive names are normalized to lowercase, matching OpenSSH behavior, you must explicitly use the `{ ignoreCase: true }` option.
fix
When using `config.compute(host)`, always pass `{ ignoreCase: true }` as the second argument if you require case-normalized output keys (e.g., `hostname` instead of `hOsTnaME`).
affects: >=4.0.0
gotchaAccording to `ssh_config(5)`, the first obtained parameter value for a given directive will be used. This library's `.compute()` method respects this rule. If multiple directives exist (e.g., `User` defined in different `Host` blocks), the one encountered first (based on specificity and order) takes precedence, and subsequent definitions for the same parameter will be ignored.
fix
Ensure that general settings are placed at the end of your SSH config file so they act as defaults, and more specific host-based settings override them earlier in the file.
affects: >=4.0.0
gotchaThe `IdentityFile` parameter, when computed via `config.compute()`, is always returned as an array, even if only one `IdentityFile` directive is present. This is to accommodate multiple `IdentityFile` settings that can coexist in an SSH config.
fix
Always expect `IdentityFile` to be an array when accessing it from the output of `config.compute()`. Iterate over the array even if you anticipate a single value.
affects: >=4.0.0
gotchaThe `.find()` method is strictly for locating and manipulating sections within the parsed config's Abstract Syntax Tree (AST). It is not designed to compute the effective configuration for a given host, which involves inheritance and precedence rules. For computed parameters, use `.compute(host)` instead.
fix
Use `config.find({ Host: 'name' })` only when you intend to modify the structure or parameters of a specific host section directly. For retrieving the final, applied SSH configuration for a host, always use `config.compute('hostname')`.
affects: >=4.0.0
Errors
Common errors & fixes
TypeError: Cannot read properties of null (reading 'config') or (reading 'add')
Attempting to parse an empty or malformed SSH configuration string.
fix
Ensure the input string to `SSHConfig.parse()` is a valid, non-empty SSH configuration. Version 5.0.4 fixed a crash on empty files, but robust error handling for invalid formats is still recommended.
Property 'compute' does not exist on type 'typeof SSHConfig' or similar TypeScript errors about method types.
Incorrect TypeScript typings or version mismatch causing `compute` method signature issues.
fix
Update to `ssh-config@^5.0.1` or later, as `v5.0.1` specifically addressed wrong typings for the `compute` method. Ensure your `tsconfig.json` includes `"allowSyntheticDefaultImports": true` if using `import SSHConfig from 'ssh-config'`.
SystemError: EPERM: operation not permitted, uv_os_get_passwd for null
`os.userInfo()` (used internally for default paths) might throw a `SystemError` if the user's home directory or other user information is unavailable or inaccessible (e.g., in a restricted environment).
fix
Version 4.4.3 specifically addressed this. Ensure you are on `ssh-config@^4.4.3` or newer. If the issue persists in highly restrictive environments, you might need to mock `os.userInfo()` or ensure the execution environment provides necessary user context.
Upgrade
Version history
0.1.6latest on npm
Audit
Dependencies

No dependency data recorded yet.

Agent activity
9 hits · last 30 days
node
8
Resources