Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ Releases before `0.2.5` predate the public launch; their notes live in the

## [Unreleased]

### Changed

- `sysknife-setup` requires Node 22 or newer. Node 18 and 20 no longer receive
security fixes, so this drops support for them rather than retiring an
untested claim: `engines.node`, the preflight guard and all six published
support statements move together, and the refusal message says why the floor
moved. Nothing in CI is affected; every job that touches JavaScript already
runs Node 24 (#327).

### Fixed

- `sysknife audit verify` now reports `cannot_verify` and exits 2 over an empty
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ plan and execute from chat.
npx sysknife-setup
```

Needs **Node 18 or newer**. On Ubuntu 22.04 `apt install nodejs` gives Node 12,
which is too old; the installer says so and how to get a current Node. No Rust
Needs **Node 22 or newer**; older Node releases no longer receive security fixes.
On Ubuntu 22.04 `apt install nodejs` gives Node 12, which is too old; the installer
says so and how to get a current Node. No Rust
toolchain and no compile: it downloads verified prebuilt binaries.

[![npm version](https://img.shields.io/npm/v/sysknife-setup?style=flat-square&logo=npm)](https://www.npmjs.com/package/sysknife-setup)
Expand Down Expand Up @@ -427,7 +428,7 @@ helps other people find the project.

| Channel | Install | Notes |
|---------|---------|-------|
| **npm** | `npx sysknife-setup` | [npmjs.com/package/sysknife-setup](https://www.npmjs.com/package/sysknife-setup) — setup wizard; needs Node 18+, no compile |
| **npm** | `npx sysknife-setup` | [npmjs.com/package/sysknife-setup](https://www.npmjs.com/package/sysknife-setup) — setup wizard; needs Node 22+, no compile |
| **crates.io** | `cargo install sysknife-cli` / `cargo install sysknife-daemon` | Needs `build-essential`; ~7-12 min build. Published by reviewed version tags; see [docs/release.md](docs/release.md) |
| **MCP Registry** | `io.github.lacs-project/sysknife` | [registry.modelcontextprotocol.io](https://registry.modelcontextprotocol.io) — resolves to the crates.io install above. Directory pages that sandbox a server list every tool but cannot call the ones needing the daemon; [docs/mcp-registry.md](docs/mcp-registry.md#what-a-directory-sandbox-can-and-cannot-tell-you) explains the split |
| **GitHub Releases** | Download from [Releases](https://github.com/lacs-project/sysknife/releases) | Prebuilt x86_64 + aarch64 binaries with SHA-256 checksums on every tag |
Expand Down
2 changes: 1 addition & 1 deletion apps/sysknife-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ containers, 6m56s on 24.04 and 11m43s on 22.04. `cmake` is **not** required.
Faster, and it installs both halves plus your MCP client config:

```sh
npx sysknife-setup # needs Node 18+
npx sysknife-setup # needs Node 22+
```

The wizard downloads SHA-256-verified binaries from the release page, so there
Expand Down
2 changes: 1 addition & 1 deletion docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ sudo systemctl enable --now sysknife-daemon
sysknife "show disk usage"
```

For prebuilt binaries instead of a build, run `npx sysknife-setup` (Node 18+).
For prebuilt binaries instead of a build, run `npx sysknife-setup` (Node 22+).
See the canonical [Quick Start](quickstart.md).

No API key needed if you have [Ollama](https://ollama.com) running locally —
Expand Down
2 changes: 1 addition & 1 deletion docs/mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ the security boundary.
npx sysknife-setup
```

Needs Node 18 or newer (Ubuntu 22.04's apt Node is 12, which is too old). The
Needs Node 22 or newer (Ubuntu 22.04's apt Node is 12, which is too old). The
wizard detects your installed `sysknife` binary, asks for the daemon socket and
LLM provider, and then asks which integration to configure. No manual file
editing needed. For install options and prerequisites in full, see the
Expand Down
2 changes: 1 addition & 1 deletion docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ needs both.
npx sysknife-setup
```

**Prerequisites:** Node 18 or newer. On Ubuntu 22.04, `apt install nodejs`
**Prerequisites:** Node 22 or newer. On Ubuntu 22.04, `apt install nodejs`
installs Node 12, which is too old — the installer will tell you so and how to
get a current Node. It downloads SHA-256-verified binaries from the release
page, installs the daemon service, and writes your MCP client config.
Expand Down
9 changes: 7 additions & 2 deletions packages/setup/node-preflight.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

/** Oldest Node the wizard's own syntax and APIs require. Keep in sync with `engines.node`. */
var MIN_MAJOR = 18;
var MIN_MAJOR = 22;

/**
* Explain, actionably, why this Node cannot run the wizard.
Expand All @@ -33,7 +33,12 @@ function unsupportedMessage(version) {
if (!isNaN(major) && major >= MIN_MAJOR) return null;

return (
'sysknife-setup needs Node ' + MIN_MAJOR + ' or newer. You are running ' + shown + '.\n' +
'sysknife-setup needs Node ' +
MIN_MAJOR +
' or newer because older releases no longer receive security fixes. ' +
'You are running ' +
shown +
'.\n' +
'\n' +
"Ubuntu 22.04's `apt install nodejs` gives Node 12, which cannot run this\n" +
'installer. Pick whichever of these suits the machine:\n' +
Expand Down
2 changes: 1 addition & 1 deletion packages/setup/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"sysknife-mcp": "mcp-launcher.js"
},
"engines": {
"node": ">=18"
"node": ">=22"
},
"files": [
"index.js",
Expand Down
38 changes: 33 additions & 5 deletions packages/setup/tests/node-preflight.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,28 @@ test('rejects the Node that Ubuntu 22.04 ships, and says how to fix it', () => {
const msg = unsupportedMessage('12.22.9');
assert.ok(msg, 'Node 12 must be rejected');
assert.match(msg, /12\.22\.9/, 'names the version actually in use');
assert.match(msg, /\b18\b/, 'names the minimum');
assert.match(msg, /\b22\b/, 'names the minimum');
assert.match(msg, /end.of.life|security fixes/i, 'explains why the floor moved');
// Actionable: at least one runnable command, not just a complaint.
assert.match(msg, /nodesource|nvm|snap|fnm/i, 'suggests a way to get a newer Node');
assert.match(msg, /releases/, 'offers the no-Node escape hatch (prebuilt binaries)');
});

test('rejects every major below the minimum and accepts every one at or above', () => {
for (const v of ['0.10.48', '4.9.1', '8.17.0', '12.22.9', '14.21.3', '16.20.2']) {
for (const v of [
'0.10.48',
'4.9.1',
'8.17.0',
'12.22.9',
'14.21.3',
'16.20.2',
'18.20.8',
'20.19.5',
'21.7.3',
]) {
assert.ok(unsupportedMessage(v), `${v} must be rejected`);
}
for (const v of ['18.0.0', '18.19.1', '20.11.0', '22.5.1', '24.0.0']) {
for (const v of ['22.0.0', '22.5.1', '24.0.0']) {
assert.equal(unsupportedMessage(v), null, `${v} must be accepted`);
}
});
Expand All @@ -66,8 +77,25 @@ test('an unparseable version is not silently treated as supported', () => {
});

test('the minimum matches what package.json advertises', () => {
assert.equal(MIN_MAJOR, 18);
assert.match(pkg.engines.node, />=\s*18/);
assert.equal(MIN_MAJOR, 22);
assert.match(pkg.engines.node, />=\s*22/);
});

test('published setup guidance names Node 22 and no longer claims Node 18 support', () => {
const repoRoot = path.resolve(pkgDir, '..', '..');
const publishedClaims = [
'README.md',
'docs/quickstart.md',
'docs/mcp.md',
'apps/sysknife-cli/README.md',
'docs/introduction.md',
];

for (const file of publishedClaims) {
const src = fs.readFileSync(path.join(repoRoot, file), 'utf8');
assert.doesNotMatch(src, /Node 18/i, `${file} must not retain the old support floor`);
assert.match(src, /Node 22/i, `${file} must name the new support floor`);
}
});

// ---------------------------------------------------------------------------
Expand Down
Loading