@klhapp/skillmux 1.12.0 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +18 -9
  3. package/bin/skillmux.js +89 -0
  4. package/docs/README.md +4 -4
  5. package/docs/cli.md +14 -4
  6. package/docs/concepts.md +2 -2
  7. package/docs/configuration.md +18 -3
  8. package/docs/deployment.md +3 -3
  9. package/docs/getting-started.md +32 -7
  10. package/docs/releasing.md +17 -2
  11. package/docs/sdd/cli-remote-target-parity/schema-bucket-b.yaml +297 -0
  12. package/docs/sdd/cli-remote-target-parity/spec-bucket-b.md +95 -0
  13. package/docs/sdd/cli-remote-target-parity/spec.md +111 -0
  14. package/docs/sdd/cli-remote-target-parity/think.md +183 -0
  15. package/docs/sdd/cli-surface-consistency/think.md +149 -0
  16. package/docs/sdd/config-authority-rerank-resilience/plan.md +338 -0
  17. package/docs/sdd/config-authority-rerank-resilience/review.md +124 -0
  18. package/docs/sdd/config-authority-rerank-resilience/spec.md +78 -0
  19. package/docs/sdd/feat-packaging-deployment/review.md +95 -0
  20. package/docs/sdd/fetch-outcome-flywheel/review.md +103 -0
  21. package/docs/sdd/fetch-outcome-flywheel/schema.json +347 -0
  22. package/docs/sdd/fetch-outcome-flywheel/spec.md +185 -0
  23. package/docs/sdd/npm-native-binaries/review.md +103 -0
  24. package/docs/sdd/npm-native-binaries/spec.md +148 -0
  25. package/docs/sdd/ranked-shortlist-2/pr3-calibration-removal.md +56 -0
  26. package/docs/sdd/refactor-builtin-target-paths/spec.md +41 -0
  27. package/docs/sdd/runtime-resource-hardening/review.md +86 -0
  28. package/docs/sdd/runtime-resource-hardening/spec.md +43 -0
  29. package/docs/sdd/security-hardening-phase/think.md +129 -0
  30. package/docs/sdd/security-observability/review.md +96 -0
  31. package/docs/sdd/security-observability/spec.md +55 -0
  32. package/docs/sdd/skill-provenance-update/review.md +152 -0
  33. package/docs/sdd/skill-provenance-update/schema.json +193 -0
  34. package/docs/sdd/skill-provenance-update/spec.md +134 -0
  35. package/docs/sdd/supply-chain-hardening/review.md +50 -0
  36. package/docs/sdd/supply-chain-hardening/spec.md +42 -0
  37. package/docs/sdd/target-marker-rehome/spec.md +33 -0
  38. package/docs/troubleshooting.md +18 -2
  39. package/package.json +15 -8
  40. package/src/adapters.ts +0 -438
  41. package/src/audit.ts +0 -21
  42. package/src/cli.ts +0 -928
  43. package/src/clients.ts +0 -368
  44. package/src/commands/audit.ts +0 -85
  45. package/src/commands/config.ts +0 -224
  46. package/src/commands/context.ts +0 -104
  47. package/src/commands/core.ts +0 -56
  48. package/src/commands/doctor.ts +0 -97
  49. package/src/commands/eval.ts +0 -88
  50. package/src/commands/init.ts +0 -672
  51. package/src/commands/install.ts +0 -155
  52. package/src/commands/local-vault.ts +0 -60
  53. package/src/commands/models.ts +0 -10
  54. package/src/commands/outdated.ts +0 -115
  55. package/src/commands/project.ts +0 -580
  56. package/src/commands/report.ts +0 -66
  57. package/src/commands/scan.ts +0 -71
  58. package/src/commands/shared.ts +0 -38
  59. package/src/commands/skill.ts +0 -33
  60. package/src/commands/sync.ts +0 -233
  61. package/src/commands/target.ts +0 -225
  62. package/src/commands/update.ts +0 -277
  63. package/src/completions.ts +0 -196
  64. package/src/concurrency-limiter.ts +0 -61
  65. package/src/config-service.ts +0 -398
  66. package/src/config-watcher.ts +0 -253
  67. package/src/config.ts +0 -583
  68. package/src/context.ts +0 -188
  69. package/src/db-audit.ts +0 -286
  70. package/src/db-index.ts +0 -238
  71. package/src/db.ts +0 -3
  72. package/src/deployment.ts +0 -39
  73. package/src/doctor.ts +0 -205
  74. package/src/eval.ts +0 -302
  75. package/src/global-flags.ts +0 -46
  76. package/src/init-agents.ts +0 -329
  77. package/src/init-instructions.ts +0 -192
  78. package/src/init.ts +0 -390
  79. package/src/install.ts +0 -232
  80. package/src/lifecycle.ts +0 -51
  81. package/src/logger.ts +0 -26
  82. package/src/manifest.ts +0 -359
  83. package/src/mcp-registration.ts +0 -89
  84. package/src/metrics.ts +0 -121
  85. package/src/models.ts +0 -20
  86. package/src/output.ts +0 -214
  87. package/src/project-setup.ts +0 -36
  88. package/src/prompts.ts +0 -124
  89. package/src/provenance.ts +0 -99
  90. package/src/rate-limiter.ts +0 -137
  91. package/src/readiness.ts +0 -30
  92. package/src/redact.ts +0 -52
  93. package/src/router-core.ts +0 -666
  94. package/src/rrf.ts +0 -31
  95. package/src/scan.ts +0 -300
  96. package/src/server.ts +0 -930
  97. package/src/setup.ts +0 -145
  98. package/src/snapshot.ts +0 -135
  99. package/src/stats.ts +0 -340
  100. package/src/sync.ts +0 -482
  101. package/src/toml-writer.ts +0 -51
  102. package/src/types.ts +0 -212
  103. package/src/vault.ts +0 -207
package/CHANGELOG.md CHANGED
@@ -5,6 +5,14 @@ All notable changes to this project are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.13.0](https://github.com/klhq/skillmux/compare/v1.12.0...v1.13.0) (2026-09-13)
9
+
10
+
11
+ ### Added
12
+
13
+ * **cli:** ship native launcher and platform packages ([#193](https://github.com/klhq/skillmux/issues/193)) ([87701d4](https://github.com/klhq/skillmux/commit/87701d44d1b647501d1dff9d205da8ffbe6a3c05))
14
+ * **sync:** make pins reach their targets, and report drift when they have not ([#192](https://github.com/klhq/skillmux/issues/192)) ([5f9c6ec](https://github.com/klhq/skillmux/commit/5f9c6ecaaaf216e4d01fa4a521ac686ae43681d3))
15
+
8
16
  ## [1.12.0](https://github.com/klhq/skillmux/compare/v1.11.2...v1.12.0) (2026-09-12)
9
17
 
10
18
 
package/README.md CHANGED
@@ -41,8 +41,8 @@ See [Configuration](docs/configuration.md#machine-config-bootstrap) and
41
41
  Choose a setup by the job:
42
42
 
43
43
  1. Need native skills or local MCP for one agent? Install the **Skillmux CLI**.
44
- 2. On Linux when Bun is undesirable? Use the **standalone Linux executable**;
45
- it is the same Skillmux CLI.
44
+ 2. Want a single file and no package manager? Download the **standalone
45
+ executable**; it is the same Skillmux CLI.
46
46
  3. Need one shared HTTP MCP service? Deploy the **full image**, the
47
47
  self-contained default with GTE-small.
48
48
  4. Already have remote embeddings, or intentionally want lexical-only
@@ -73,19 +73,28 @@ model runs in the Skillmux process. Both stdio and HTTP expose the same
73
73
 
74
74
  ## Install the CLI
75
75
 
76
- The Bun package supports macOS, Linux, and Windows and requires
77
- [Bun 1.3 or newer](https://bun.sh/docs/installation):
76
+ Skillmux ships as a native executable, so there is no runtime to install
77
+ alongside it. Any of these works on macOS, Linux, and Windows:
78
78
 
79
79
  ```sh
80
+ npm install -g @klhapp/skillmux
80
81
  bun add -g @klhapp/skillmux
81
- skillmux --help
82
+ npx @klhapp/skillmux --help
82
83
  ```
83
84
 
84
- Native target sync needs permission to create directory symlinks on Windows.
85
+ Installing pulls exactly one platform-specific executable through
86
+ `optionalDependencies`, so you download the build for your machine and not the
87
+ other four. Native target sync needs permission to create directory symlinks
88
+ on Windows.
85
89
 
86
- On Linux, you can install a standalone executable instead. This path needs no
87
- GitHub CLI or package manager. It selects AMD64 or ARM64, downloads the pinned
88
- `v1.3.4` release, and verifies the SHA-256 digest published for that release:
90
+ Local embedding inference is included on every platform except Intel macOS.
91
+ See [platform support](docs/getting-started.md#platform-support) for what that
92
+ costs and why.
93
+
94
+ You can also install a standalone executable and skip package managers
95
+ entirely. Every release attaches one per platform. This path needs no GitHub
96
+ CLI. It selects AMD64 or ARM64, downloads the pinned `v1.3.4` release, and
97
+ verifies the SHA-256 digest published for that release:
89
98
 
90
99
  ```sh
91
100
  version=v1.3.4
@@ -0,0 +1,89 @@
1
+ #!/bin/sh
2
+ // 2>/dev/null; exec "$(command -v bun || command -v node)" "$0" "$@"
3
+ import { spawn } from "node:child_process";
4
+ import { existsSync } from "node:fs";
5
+ import { createRequire } from "node:module";
6
+ import { constants } from "node:os";
7
+ import { delimiter, dirname, join } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+
10
+ const require = createRequire(import.meta.url);
11
+ // `new URL(...).pathname` yields "/C:/..." on Windows; fileURLToPath does not.
12
+ const here = dirname(fileURLToPath(import.meta.url));
13
+
14
+ const platformPackage = `@klhapp/skillmux-${process.platform}-${process.arch}`;
15
+ const executableName = process.platform === "win32" ? "skillmux.exe" : "skillmux";
16
+
17
+ /**
18
+ * Resolves the platform package directory.
19
+ *
20
+ * The search paths matter: a globally installed launcher resolves from its own
21
+ * directory, while a linked or hoisted layout can leave the real path outside
22
+ * the install tree, which is what the working directory covers.
23
+ */
24
+ function resolvePackageDir() {
25
+ try {
26
+ return dirname(
27
+ require.resolve(`${platformPackage}/package.json`, {
28
+ paths: [here, dirname(process.argv[1] ?? "."), process.cwd()],
29
+ }),
30
+ );
31
+ } catch {
32
+ return null;
33
+ }
34
+ }
35
+
36
+ const packageDir = resolvePackageDir();
37
+
38
+ if (!packageDir && !process.env.SKILLMUX_BINARY) {
39
+ process.stderr.write(
40
+ `skillmux: no native executable for ${process.platform}-${process.arch}.\n` +
41
+ `The package ${platformPackage} is not installed.\n\n` +
42
+ "Reinstall without skipping optional dependencies:\n" +
43
+ " npm install -g @klhapp/skillmux\n\n" +
44
+ "Or install a standalone executable:\n" +
45
+ " https://github.com/klhq/skillmux/releases\n",
46
+ );
47
+ process.exit(1);
48
+ }
49
+
50
+ const executable = process.env.SKILLMUX_BINARY || join(packageDir, executableName);
51
+
52
+ // The compiled binary embeds onnxruntime's addon but not the library it links
53
+ // against, so without this the local embedding pipeline dies on a dlopen of
54
+ // @rpath/libonnxruntime. Platforms onnxruntime does not publish, such as Intel
55
+ // macOS, ship no lib directory and fall back to lexical recall.
56
+ const LIBRARY_PATH_VARIABLES = {
57
+ darwin: "DYLD_FALLBACK_LIBRARY_PATH",
58
+ linux: "LD_LIBRARY_PATH",
59
+ win32: "PATH",
60
+ };
61
+
62
+ const env = { ...process.env };
63
+ const libraryDir = packageDir ? join(packageDir, "lib") : null;
64
+ const libraryVariable = LIBRARY_PATH_VARIABLES[process.platform];
65
+
66
+ if (libraryDir && libraryVariable && existsSync(libraryDir)) {
67
+ const existing = env[libraryVariable];
68
+ env[libraryVariable] = existing ? `${libraryDir}${delimiter}${existing}` : libraryDir;
69
+ }
70
+
71
+ const child = spawn(executable, process.argv.slice(2), { stdio: "inherit", env });
72
+
73
+ // Without this the launcher would absorb the signal and leave the executable
74
+ // running, which matters most for `serve`: a container stop sends SIGTERM and
75
+ // expects the HTTP server itself to shut down.
76
+ for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
77
+ process.on(signal, () => {
78
+ if (child.exitCode === null && child.signalCode === null) child.kill(signal);
79
+ });
80
+ }
81
+
82
+ child.on("error", (error) => {
83
+ process.stderr.write(`skillmux: cannot run ${executable}: ${error.message}\n`);
84
+ process.exit(1);
85
+ });
86
+
87
+ child.on("exit", (code, signal) => {
88
+ process.exit(signal ? 128 + (constants.signals[signal] ?? 0) : (code ?? 1));
89
+ });
package/docs/README.md CHANGED
@@ -9,7 +9,7 @@ where skills need to appear and where Skillmux should run.
9
9
 
10
10
  1. [Install the Skillmux CLI](getting-started.md#install-the-cli) for native
11
11
  skills or one local MCP client.
12
- 2. On Linux, use the [standalone executable install](getting-started.md#install-the-cli)
12
+ 2. Use the [standalone executable install](getting-started.md#standalone-executable)
13
13
  when you want a pinned, checksum-verified CLI without `gh`; the
14
14
  [GitHub CLI attestation path](getting-started.md#install-with-github-cli-attestation)
15
15
  is also available for provenance verification.
@@ -19,9 +19,9 @@ where skills need to appear and where Skillmux should run.
19
19
 
20
20
  You can combine native management and local MCP retrieval on one machine. For
21
21
  native pins plus shared retrieval, run Skillmux CLI on each machine that owns
22
- agent directories and deploy Skillmux server for HTTP MCP. The Bun package is
23
- the cross-platform CLI installation method; the standalone Linux executable is
24
- its Linux alternative. Git and the deployment process, not Skillmux, replicate
22
+ agent directories and deploy Skillmux server for HTTP MCP. The CLI installs
23
+ through npm or bun on every supported platform, with a direct executable
24
+ download as the package-manager-free alternative. Git and the deployment process, not Skillmux, replicate
25
25
  vault checkouts and determine their freshness; see
26
26
  [Deployment](deployment.md#native-pins-with-shared-retrieval).
27
27
 
package/docs/cli.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # CLI reference and automation
2
2
 
3
- The Bun package and standalone Linux executable expose the same Skillmux CLI.
4
- For Linux installation, use the [pinned checksum-verified download](getting-started.md#install-the-cli)
3
+ Every installation path delivers the same Skillmux CLI executable. For a
4
+ package-manager-free install, use the [pinned checksum-verified download](getting-started.md#standalone-executable)
5
5
  or, when provenance verification is required, the
6
6
  [attested GitHub CLI path](getting-started.md#install-with-github-cli-attestation).
7
7
  Native management belongs on the machine that owns the agent skill directories:
@@ -315,7 +315,10 @@ skillmux target remove custom-agent --yes
315
315
  `target add` uses the same ownership, symlink, full-vault, rollback, and
316
316
  current-host scoping checks as `skillmux init`. `target remove` removes the
317
317
  manifest entry and preserves the directory, marker, and skill files. The
318
- command prints the preserved path so cleanup remains an explicit user action.
318
+ command prints the preserved path so cleanup remains an explicit user action. `target add` syncs once the
319
+ target is recorded, so the new directory is populated in one command; the
320
+ approval just given named that exact directory, so it carries through. Pass
321
+ `--no-sync` to record the target without populating it.
319
322
 
320
323
  ---
321
324
 
@@ -328,12 +331,17 @@ default, capped at 25 skills unless `[core].limit` raises it:
328
331
  skillmux core pin csv-formatter --yes
329
332
  skillmux core pin csv-formatter pdf-extractor terraform-plans --yes
330
333
  skillmux core unpin csv-formatter --yes
334
+ skillmux core pin csv-formatter --yes --no-sync # manifest only; sync later
331
335
  ```
332
336
 
333
337
  One or more `skill_id` arguments are accepted per call and applied
334
338
  atomically against a single in-memory manifest: if any one of them is
335
339
  already pinned elsewhere (or, for `unpin`, not currently pinned), the
336
- whole call fails and the manifest file is left untouched. To pin into a
340
+ whole call fails and the manifest file is left untouched. Both commands
341
+ then sync, so a pin reaches every target directory in one command; `--json`
342
+ returns the per-target result in the same envelope. Pass `--no-sync` to
343
+ write the manifest alone. A target directory this machine has never synced
344
+ still needs its own approval, so a pin never creates one. To pin into a
337
345
  `[project.<group>]` tier instead, use `skillmux project pin` (see
338
346
  [Project Setup](#project-setup-skillmux-project-init)).
339
347
 
@@ -467,6 +475,8 @@ Named CLI contexts (`--context <name>` or `--server <url>`) support the followin
467
475
  - `skillmux eval promote --since <window>`: fetches promotable candidates from the remote server's audit db via `POST /admin/v1/eval/promote`, dedups against the local fixture file, and writes locally.
468
476
  - `skillmux doctor`: inspects remote server status, readiness, deployment runtime, and capabilities without requiring local vault access.
469
477
 
478
+ Run on a host, `doctor` also reports `sync_drift`: a planned-but-never-performed sync naming every target directory whose contents no longer match what the manifest pins. Targets scoped to another `host` are excluded, and the check is omitted altogether in a container, which serves skills without owning a target directory.
479
+
470
480
  ---
471
481
 
472
482
  ## Color
package/docs/concepts.md CHANGED
@@ -80,8 +80,8 @@ flowchart TD
80
80
  | Local MCP | Beside one client | stdio | Skillmux CLI |
81
81
  | Shared MCP | Server or container host | Streamable HTTP | Skillmux server (full image) |
82
82
 
83
- The **Skillmux CLI** is available as either the Bun package or the standalone
84
- Linux executable; both expose the same commands. The **full image** is the
83
+ The **Skillmux CLI** is one native executable per platform, installed through
84
+ npm, bun, or a direct download; every path exposes the same commands. The **full image** is the
85
85
  default Skillmux server deployment. The **slim image** is an
86
86
  advanced variant for configured remote embeddings or intentional lexical-only
87
87
  retrieval. The CLI can also serve HTTP, and Docker can serve stdio for clients
@@ -297,7 +297,7 @@ project_groups = ["repo1"] # which [project.*] groups materialize into
297
297
  ```
298
298
 
299
299
  - `[core].skills`: symlinked into every `[targets.*]` dir on `sync`. Capped at 25 skills unless `[core].limit` says otherwise; `sync` fails if a listed skill id isn't actually in the vault.
300
- - `[core].limit` (optional, positive integer): the cap on `[core].skills`. Absent means 25. It lives in the manifest rather than machine config so the same manifest validates identically on every machine.
300
+ - `[core].limit` (optional, positive integer): the cap on `[core].skills`. Absent means 25. Exceeding it fails with an error naming this key, because the cap is a budget on how much skill frontmatter every agent carries in its system prompt, not a structural limit. It lives in the manifest rather than machine config so the same manifest validates identically on every machine.
301
301
  - `[project.<group>].skills`: symlinked only into `<path>/<relative path from $HOME to the target dir>`, for each `paths` entry, and only for targets whose `project_groups` names that group. `paths` entries must resolve under `$HOME` (that's how the pin path is derived). A skill can't appear in both `[core]` and the same `[project.*]` group.
302
302
  - `[project.<group>].paths` can list the same project's checkout on more than one machine (e.g. `["/home/alice/code/repo1", "/Users/alice/code/repo1"]`). `sync` silently skips any entry that doesn't exist on the machine it's running on (see below), so one shared manifest can span machines with different checkout locations without needing per-machine manifests.
303
303
  - `[targets.<name>]`: one entry per adopted surface. Built-in names (`agent-skills`, `claude-code`, and `codex`) derive their directories from the name and omit `dir`. A custom target requires `dir`; create one with `skillmux target add <name> --dir <dir> --yes`. `skillmux target migrate --yes` removes legacy built-in `dir` fields without touching target files. An optional `host` limits the target to an exact machine-hostname match; omit it for a global, backward-compatible target. A host mismatch is reported and skipped before any target filesystem operation. `project_groups` is an explicit list, not a boolean: a target only receives the specific groups it names, never every group in the manifest.
@@ -313,7 +313,15 @@ skillmux core unpin csv-formatter pdf-extractor --yes # unpin
313
313
  skillmux project unpin repo1 pdf-extractor --yes # remove from a group (group stays, even if empty)
314
314
  ```
315
315
 
316
- Both commands accept one or more `skill_id` arguments per call; all of them are validated and applied against a single in-memory manifest before anything is written, so if any one of them is already pinned elsewhere (or, for unpin, not currently pinned), the whole call fails and the manifest file is left untouched: no partial pins. To pin into a `[project.<group>]` tier that doesn't exist yet, create it first with `skillmux project add-path <group> <path> --yes`. Hand-editing `skillmux.toml` directly is still fully supported; these commands are a convenience layer over the same file, not a replacement for it.
316
+ Both commands accept one or more `skill_id` arguments per call; all of them are validated and applied against a single in-memory manifest before anything is written, so if any one of them is already pinned elsewhere (or, for unpin, not currently pinned), the whole call fails and the manifest file is left untouched: no partial pins.
317
+
318
+ Pinning syncs. Writing the manifest is only half the job, since the pin stays invisible to
319
+ every agent until the symlinks move, so both commands run the sync themselves and report
320
+ what each target gained or lost. Under `--json` that arrives inside the same envelope as a
321
+ `targets` array, never as a second document. Pass `--no-sync` to write the manifest alone,
322
+ which is what you want when batching several pins before one sync. The pin's own `--yes`
323
+ answers "pin this skill" and is deliberately not forwarded: a target directory this machine
324
+ has never synced still needs its own approval, so a pin can never silently create one. To pin into a `[project.<group>]` tier that doesn't exist yet, create it first with `skillmux project add-path <group> <path> --yes`. Hand-editing `skillmux.toml` directly is still fully supported; these commands are a convenience layer over the same file, not a replacement for it.
317
325
 
318
326
  > **Breaking change:** `skillmux manifest pin`/`unpin` is removed. `[core]` pinning is now `skillmux core pin`/`unpin`; `[project.*]` pinning was already available as `skillmux project pin`/`unpin` and is now the only way to do it. There's no more `--path`-based inline group creation from a pin call; use `project add-path` to create the group first.
319
327
  >
@@ -326,7 +334,14 @@ Every `[core]`/`[project.*]` skill_id must resolve from the configured
326
334
  `local_vault_paths` entry (see below) fails `sync` with a distinct error, since
327
335
  the manifest is meant to be portable across machines and a machine-local
328
336
  override wouldn't exist elsewhere. `doctor` validates the manifest as part of
329
- its checks, surfacing any violation without writing anything back.
337
+ its checks, surfacing any violation without writing anything back. Its `sync_drift` check
338
+ goes one step further and plans (never performs) the sync this machine would run, naming
339
+ every target directory whose contents no longer match what the manifest pins. A manifest
340
+ pulled in from another machine, a `--no-sync` pin, and a hand-edit can all produce that
341
+ gap. A target scoped to another `host` is left out, since this machine is not the one that
342
+ syncs it, and the check is omitted entirely in a container: targets are a local delivery
343
+ concern, and a container serving the MCP surface reads the vault to answer `resolve_skill`
344
+ and `fetch_skill` without owning a target directory at all.
330
345
 
331
346
  ### Ownership marker
332
347
 
@@ -9,9 +9,9 @@ Choose a deployment from the client count and inference source:
9
9
  | Shared MCP with local inference | Skillmux server (full image) | Streamable HTTP | Bundled GTE-small |
10
10
  | Shared MCP with remote or lexical retrieval | Skillmux server (slim image, advanced) | Streamable HTTP | Remote endpoint or lexical fallback |
11
11
 
12
- Install the CLI with either the Bun package or standalone Linux executable;
13
- they expose the same commands and can also serve HTTP. The Linux executable
14
- has a [pinned, checksum-verified download](getting-started.md#install-the-cli)
12
+ Install the CLI with npm, bun, or a direct executable download; every path
13
+ delivers the same commands and can also serve HTTP. The direct download has a
14
+ [pinned, checksum-verified procedure](getting-started.md#standalone-executable)
15
15
  that defaults to `~/.local/bin`, plus an
16
16
  [attested GitHub CLI path](getting-started.md#install-with-github-cli-attestation).
17
17
  Deploy the full image
@@ -26,18 +26,44 @@ vault.
26
26
 
27
27
  ## Install the CLI
28
28
 
29
- Use the Bun package on macOS, Linux, or Windows. It requires
30
- [Bun 1.3 or newer](https://bun.sh/docs/installation):
29
+ Skillmux ships as a native executable for each supported platform, so no
30
+ runtime needs to be present. Use whichever package manager you already have:
31
31
 
32
32
  ```sh
33
+ npm install -g @klhapp/skillmux
33
34
  bun add -g @klhapp/skillmux
34
- skillmux --help
35
+ npx @klhapp/skillmux --help
35
36
  ```
36
37
 
38
+ The package declares one `optionalDependencies` entry per platform, each
39
+ marked with its `os` and `cpu`. npm and bun install the single entry that
40
+ matches the current machine and skip the rest, so an install fetches one
41
+ executable rather than five.
42
+
37
43
  Native target sync needs permission to create directory symlinks on Windows.
38
44
 
39
- Linux users can install the standalone executable without the GitHub CLI or a
40
- package manager. This example selects AMD64 or ARM64, downloads the pinned
45
+ ### Platform support
46
+
47
+ | Platform | Executable | Local embedding inference |
48
+ | --- | --- | --- |
49
+ | macOS Apple Silicon | Yes | Yes |
50
+ | macOS Intel | Yes | No, lexical recall only |
51
+ | Linux x86-64 | Yes | Yes |
52
+ | Linux ARM64 | Yes | Yes |
53
+ | Windows x86-64 | Yes | Yes |
54
+
55
+ Intel macOS is the one gap, and it is not a deliberate one. `onnxruntime-node`
56
+ stopped shipping its Intel macOS binding in the 1.23 series, so there is no
57
+ ONNX Runtime to embed for that platform. Everything else works there; only the
58
+ embedding lane falls back to lexical recall. Configure
59
+ [remote inference](configuration.md) if you need ranked retrieval on an Intel
60
+ Mac. Skillmux detects the binding at build time rather than consulting a fixed
61
+ list, so the platform regains local inference as soon as upstream restores it.
62
+
63
+ ### Standalone executable
64
+
65
+ Every release also attaches one executable per platform, which skips package
66
+ managers entirely. This example selects AMD64 or ARM64, downloads the pinned
41
67
  `v1.3.4` release, verifies the SHA-256 digest published for that release, and
42
68
  installs to the user-writable default `~/.local/bin`:
43
69
 
@@ -77,8 +103,7 @@ gh attestation verify "$bin_dir/$asset" --repo klhq/skillmux
77
103
  install -m755 "$bin_dir/$asset" "$bin_dir/skillmux"
78
104
  ```
79
105
 
80
- The Bun package and standalone Linux executable expose the same Skillmux CLI
81
- commands.
106
+ Every installation path delivers the same executable and the same commands.
82
107
 
83
108
  ## Prepare a vault checkout
84
109
 
package/docs/releasing.md CHANGED
@@ -35,11 +35,16 @@ accidentally republish an existing npm version.
35
35
 
36
36
  The release workflow publishes:
37
37
 
38
+ - `@klhapp/skillmux-<platform>-<arch>` for each of the five supported
39
+ platforms, published before the root package
38
40
  - `@klhapp/skillmux` to the public npm registry
39
41
  - `@klhq/skillmux` to GitHub Packages, linked to this repository
40
42
  - `skillmux-linux-amd64`
41
43
  - `skillmux-linux-arm64`
42
- - SHA-256 digests for the Linux binaries in the GitHub Release asset metadata
44
+ - `skillmux-darwin-arm64`
45
+ - `skillmux-darwin-x64`
46
+ - `skillmux-win32-x64.exe`
47
+ - SHA-256 digests for the binaries in the GitHub Release asset metadata
43
48
  - GitHub build provenance attestations when the repository is public
44
49
  - Skillmux server full image to GHCR and Docker Hub: `:<version>`, `:<major>.<minor>`,
45
50
  and `:latest`; this variant includes GTE-small
@@ -72,7 +77,17 @@ The `production-release` GitHub environment provides the
72
77
  `DOCKERHUB_USERNAME` variable and `DOCKERHUB_TOKEN` secret. The npmjs job also
73
78
  uses this environment as its Trusted Publisher identity; configure npm with
74
79
  workflow `release-please.yml` and environment `production-release`. No
75
- long-lived npm token is required. The GitHub Packages job uses the workflow's
80
+ long-lived npm token is required.
81
+
82
+ The `npm-platform` job publishes the five platform packages under the same
83
+ identity, so each of those package names needs its own Trusted Publisher entry
84
+ with the same workflow and environment. Configure all five before the first
85
+ release that includes them. A package name npm has never seen may need one
86
+ manual publish before its Trusted Publisher can be configured; if so, publish
87
+ that first version by hand and let the workflow take over from the next
88
+ release. Order matters at publish time as well as at install time: the root
89
+ package pins the platform packages exactly, so publishing it first would leave
90
+ every install resolving a version that does not exist yet. The GitHub Packages job uses the workflow's
76
91
  scoped `GITHUB_TOKEN` and changes only its runner-local package name to
77
92
  `@klhq/skillmux`; the source package remains `@klhapp/skillmux` for npmjs.
78
93