@klhapp/skillmux 1.7.0 → 1.8.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.
- package/CHANGELOG.md +14 -0
- package/README.md +14 -5
- package/docs/assets/architecture-dark.svg +160 -0
- package/docs/assets/{architecture.svg → architecture-light.svg} +40 -34
- package/docs/assets/logo-dark.png +0 -0
- package/docs/assets/logo-light.png +0 -0
- package/docs/cli.md +63 -5
- package/docs/concepts.md +10 -0
- package/docs/configuration.md +20 -20
- package/docs/deployment.md +20 -7
- package/docs/getting-started.md +11 -0
- package/docs/mcp-routing.md +41 -7
- package/docs/schema.json +31 -4
- package/package.json +1 -1
- package/src/audit.ts +1 -0
- package/src/cli.ts +29 -9
- package/src/commands/audit.ts +82 -0
- package/src/commands/eval.ts +81 -0
- package/src/config-service.ts +2 -2
- package/src/config.ts +10 -4
- package/src/db.ts +152 -45
- package/src/eval.ts +69 -0
- package/src/router-core.ts +95 -24
- package/src/server.ts +21 -6
- package/src/stats.ts +119 -13
- package/src/types.ts +22 -0
- package/docs/assets/logo.png +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@ 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.8.0](https://github.com/klhq/skillmux/compare/v1.7.1...v1.8.0) (2026-08-28)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
* **audit:** add fetch-outcome routing quality flywheel ([#131](https://github.com/klhq/skillmux/issues/131)) ([c55e5ec](https://github.com/klhq/skillmux/commit/c55e5ec794453ccbdbf7ffe9263684356d2a71de))
|
|
14
|
+
|
|
15
|
+
## [1.7.1](https://github.com/klhq/skillmux/compare/v1.7.0...v1.7.1) (2026-08-21)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
* **config:** neutralize migration error wording ([#128](https://github.com/klhq/skillmux/issues/128)) ([1fb130e](https://github.com/klhq/skillmux/commit/1fb130e3a6c3c3c084ca183c67ab7c8f984595a7))
|
|
21
|
+
|
|
8
22
|
## [1.7.0](https://github.com/klhq/skillmux/compare/v1.6.0...v1.7.0) (2026-08-21)
|
|
9
23
|
|
|
10
24
|
|
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/klhq/skillmux/main/docs/assets/logo-dark.png">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/klhq/skillmux/main/docs/assets/logo-light.png" alt="skillmux" width="400">
|
|
5
|
+
</picture>
|
|
3
6
|
</p>
|
|
4
7
|
|
|
5
8
|
<p align="center">
|
|
@@ -9,9 +12,12 @@
|
|
|
9
12
|
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
|
|
10
13
|
</p>
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
<p align="center"><strong>One skill vault. Every AI coding client. Nothing lost in translation.</strong></p>
|
|
16
|
+
|
|
17
|
+
Every AI coding client wants its own skill folder and its own format. Skillmux
|
|
18
|
+
manages [`SKILL.md`](https://agentskills.io) collections across all of them
|
|
19
|
+
from one place. Keep one **vault source of truth** (the logical skill
|
|
20
|
+
collection), pin a small set into native skill directories, and retrieve the
|
|
15
21
|
rest through MCP. A **vault checkout** is a physical copy of that collection.
|
|
16
22
|
On one machine, `~/skills` can be both the source of truth and its checkout.
|
|
17
23
|
|
|
@@ -55,7 +61,10 @@ command to run; see the [container command contract](docs/deployment.md#containe
|
|
|
55
61
|
## One vault source of truth, three ways to use it
|
|
56
62
|
|
|
57
63
|
<p align="center">
|
|
58
|
-
<
|
|
64
|
+
<picture>
|
|
65
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/assets/architecture-dark.svg">
|
|
66
|
+
<img src="docs/assets/architecture-light.svg" alt="Three ways to use Skillmux: manage native skills, add local MCP retrieval, or run a shared MCP service" width="100%">
|
|
67
|
+
</picture>
|
|
59
68
|
</p>
|
|
60
69
|
|
|
61
70
|
“Local” describes where Skillmux runs. “Local inference” means the embedding
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 720" role="img" aria-labelledby="title desc">
|
|
2
|
+
<title id="title">One vault source of truth, three ways to use Skillmux</title>
|
|
3
|
+
<desc id="desc">One Git-backed vault source of truth holds one SKILL.md per child directory and feeds a client checkout and a server checkout. On a client machine, Skillmux CLI manages native skills and serves local stdio MCP; a server checkout serves shared Streamable HTTP MCP. resolve_skill fuses lexical and vector results and optionally reranks them; fetch_skill returns the current SKILL.md bytes with a SHA-256. Git and deployment own checkout replication and freshness.</desc>
|
|
4
|
+
|
|
5
|
+
<defs>
|
|
6
|
+
<filter id="shadow" x="-15%" y="-15%" width="130%" height="140%">
|
|
7
|
+
<feDropShadow dx="0" dy="5" stdDeviation="8" flood-color="#000000" flood-opacity="0.35"/>
|
|
8
|
+
</filter>
|
|
9
|
+
<marker id="arrow-teal" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
|
|
10
|
+
<path d="M0 0L10 5L0 10Z" fill="#2dd4bf"/>
|
|
11
|
+
</marker>
|
|
12
|
+
<marker id="arrow-blue" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
|
|
13
|
+
<path d="M0 0L10 5L0 10Z" fill="#60a5fa"/>
|
|
14
|
+
</marker>
|
|
15
|
+
<marker id="arrow-violet" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
|
|
16
|
+
<path d="M0 0L10 5L0 10Z" fill="#a78bfa"/>
|
|
17
|
+
</marker>
|
|
18
|
+
<style>
|
|
19
|
+
text {
|
|
20
|
+
font-family: "DejaVu Sans", Arial, sans-serif;
|
|
21
|
+
}
|
|
22
|
+
.title {
|
|
23
|
+
font-size: 27px;
|
|
24
|
+
font-weight: 750;
|
|
25
|
+
fill: #e2e8f0;
|
|
26
|
+
}
|
|
27
|
+
.subtitle {
|
|
28
|
+
font-size: 16px;
|
|
29
|
+
font-weight: 400;
|
|
30
|
+
fill: #94a3b8;
|
|
31
|
+
}
|
|
32
|
+
.card-title {
|
|
33
|
+
font-size: 21px;
|
|
34
|
+
font-weight: 750;
|
|
35
|
+
fill: #e2e8f0;
|
|
36
|
+
}
|
|
37
|
+
.label {
|
|
38
|
+
font-size: 15px;
|
|
39
|
+
font-weight: 650;
|
|
40
|
+
fill: #cbd5e1;
|
|
41
|
+
}
|
|
42
|
+
.body {
|
|
43
|
+
font-size: 14px;
|
|
44
|
+
font-weight: 400;
|
|
45
|
+
fill: #94a3b8;
|
|
46
|
+
}
|
|
47
|
+
.mono {
|
|
48
|
+
font-family: "DejaVu Sans Mono", Consolas, monospace;
|
|
49
|
+
font-size: 14px;
|
|
50
|
+
font-weight: 650;
|
|
51
|
+
fill: #cbd5e1;
|
|
52
|
+
}
|
|
53
|
+
.mono-light {
|
|
54
|
+
fill: #ffffff;
|
|
55
|
+
}
|
|
56
|
+
.chip {
|
|
57
|
+
font-size: 12px;
|
|
58
|
+
font-weight: 750;
|
|
59
|
+
letter-spacing: .5px;
|
|
60
|
+
}
|
|
61
|
+
</style>
|
|
62
|
+
</defs>
|
|
63
|
+
|
|
64
|
+
<rect width="1200" height="720" rx="24" fill="#0d1117"/>
|
|
65
|
+
<rect x="1" y="1" width="1198" height="718" rx="23" fill="none" stroke="#30363d" stroke-width="2"/>
|
|
66
|
+
|
|
67
|
+
<text x="48" y="50" class="title">One vault source of truth, three ways to use Skillmux</text>
|
|
68
|
+
<text x="48" y="78" class="subtitle">Git and deployment replicate checkouts; Skillmux uses each checkout where it runs.</text>
|
|
69
|
+
|
|
70
|
+
<g filter="url(#shadow)">
|
|
71
|
+
<rect x="280" y="106" width="640" height="118" rx="18" fill="#161b22" stroke="#30363d" stroke-width="2"/>
|
|
72
|
+
<circle cx="324" cy="147" r="18" fill="#334155"/>
|
|
73
|
+
<path d="M314 141H327L333 147L327 153H314M320 135V159" fill="none" stroke="#ffffff" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
74
|
+
<text x="358" y="144" class="card-title">Git-backed vault source of truth</text>
|
|
75
|
+
<text x="358" y="172" class="mono">SKILL.md per child directory</text>
|
|
76
|
+
<text x="358" y="200" class="body">A checkout is a physical copy of it on one machine.</text>
|
|
77
|
+
<rect x="751" y="155" width="137" height="34" rx="9" fill="#1e293b" stroke="#475569"/>
|
|
78
|
+
<text x="819.5" y="177" text-anchor="middle" class="mono">skillmux.toml</text>
|
|
79
|
+
</g>
|
|
80
|
+
|
|
81
|
+
<path d="M520 224V252H410V277" fill="none" stroke="#2dd4bf" stroke-width="3" marker-end="url(#arrow-teal)"/>
|
|
82
|
+
<path d="M720 224V252H980V277" fill="none" stroke="#a78bfa" stroke-width="3" marker-end="url(#arrow-violet)"/>
|
|
83
|
+
<text x="394" y="270" text-anchor="end" class="body">client checkout</text>
|
|
84
|
+
<text x="996" y="270" text-anchor="start" class="body">server checkout</text>
|
|
85
|
+
|
|
86
|
+
<g filter="url(#shadow)">
|
|
87
|
+
<rect x="40" y="284" width="740" height="302" rx="18" fill="#161b22" stroke="#0f766e" stroke-width="2"/>
|
|
88
|
+
<rect x="62" y="306" width="124" height="26" rx="13" fill="#134e4a"/>
|
|
89
|
+
<text x="124" y="324" text-anchor="middle" class="chip" fill="#5eead4">SKILLMUX CLI</text>
|
|
90
|
+
<text x="62" y="365" class="card-title">On one client machine</text>
|
|
91
|
+
<text x="62" y="390" class="body">Manage native skills, add local MCP retrieval, or do both.</text>
|
|
92
|
+
|
|
93
|
+
<rect x="62" y="414" width="276" height="48" rx="10" fill="#0f2e2b" stroke="#0f766e"/>
|
|
94
|
+
<circle cx="85" cy="438" r="11" fill="#2dd4bf"/>
|
|
95
|
+
<text x="85" y="442.5" text-anchor="middle" style="font-size: 13px; font-weight: 750" fill="#0d1117">1</text>
|
|
96
|
+
<text x="200" y="433" text-anchor="middle" class="label" style="font-size: 17px">Manage native skills</text>
|
|
97
|
+
<text x="200" y="453" text-anchor="middle" class="mono">skillmux init · sync</text>
|
|
98
|
+
<path d="M200 462V487" fill="none" stroke="#2dd4bf" stroke-width="2.5" marker-end="url(#arrow-teal)"/>
|
|
99
|
+
<rect x="62" y="493" width="276" height="49" rx="10" fill="#1e293b" stroke="#475569"/>
|
|
100
|
+
<text x="200" y="514" text-anchor="middle" class="label">Native skill directories</text>
|
|
101
|
+
<text x="200" y="533" text-anchor="middle" class="body">managed core and project links</text>
|
|
102
|
+
|
|
103
|
+
<text x="62" y="570" class="body">Install Skillmux CLI with</text>
|
|
104
|
+
<rect x="270" y="550" width="85" height="27" rx="8" fill="#0f172a" stroke="#334155"/>
|
|
105
|
+
<text x="312.5" y="568" text-anchor="middle" class="chip" style="font-size: 10px" fill="#ffffff">BUN PACKAGE</text>
|
|
106
|
+
<rect x="361" y="550" width="87" height="27" rx="8" fill="#1e293b" stroke="#475569"/>
|
|
107
|
+
<text x="404.5" y="561" text-anchor="middle" class="chip" style="font-size: 10px" fill="#cbd5e1"><tspan x="404.5">LINUX</tspan><tspan x="404.5" dy="11">EXECUTABLE</tspan></text>
|
|
108
|
+
</g>
|
|
109
|
+
|
|
110
|
+
<g filter="url(#shadow)">
|
|
111
|
+
<rect x="420" y="414" width="338" height="128" rx="10" fill="#172554" stroke="#3b82f6"/>
|
|
112
|
+
<circle cx="453" cy="435" r="11" fill="#60a5fa"/>
|
|
113
|
+
<text x="453" y="439.5" text-anchor="middle" style="font-size: 13px; font-weight: 750" fill="#0d1117">2</text>
|
|
114
|
+
<text x="476" y="441" class="label" style="font-size: 17px">Add local MCP retrieval</text>
|
|
115
|
+
<text x="442" y="463" class="body">Reaches the whole indexed vault on demand.</text>
|
|
116
|
+
|
|
117
|
+
<rect x="442" y="475" width="92" height="48" rx="10" fill="#1e293b" stroke="#475569"/>
|
|
118
|
+
<text x="488" y="505" text-anchor="middle" class="label">AI client</text>
|
|
119
|
+
<path d="M534 499H578" fill="none" stroke="#60a5fa" stroke-width="2.5" marker-end="url(#arrow-blue)"/>
|
|
120
|
+
<text x="559" y="489" text-anchor="middle" class="body">stdio</text>
|
|
121
|
+
<rect x="584" y="470" width="152" height="62" rx="10" fill="#161b22" stroke="#3b82f6"/>
|
|
122
|
+
<text x="660" y="492" text-anchor="middle" class="mono">skillmux serve</text>
|
|
123
|
+
<text x="660" y="511" text-anchor="middle" class="body">default: FTS5 +</text>
|
|
124
|
+
<text x="660" y="527" text-anchor="middle" class="body">local GTE-small</text>
|
|
125
|
+
|
|
126
|
+
</g>
|
|
127
|
+
|
|
128
|
+
<g filter="url(#shadow)">
|
|
129
|
+
<rect x="800" y="284" width="360" height="302" rx="18" fill="#161b22" stroke="#7c3aed" stroke-width="2"/>
|
|
130
|
+
<rect x="822" y="306" width="136" height="26" rx="13" fill="#312e81"/>
|
|
131
|
+
<text x="890" y="324" text-anchor="middle" class="chip" fill="#c4b5fd">SKILLMUX SERVER</text>
|
|
132
|
+
<circle cx="833" cy="358" r="11" fill="#a78bfa"/>
|
|
133
|
+
<text x="833" y="362.5" text-anchor="middle" style="font-size: 13px; font-weight: 750" fill="#0d1117">3</text>
|
|
134
|
+
<text x="856" y="365" class="card-title">Run a shared MCP service</text>
|
|
135
|
+
<text x="822" y="390" class="body">Read a server checkout to serve several clients.</text>
|
|
136
|
+
|
|
137
|
+
<rect x="822" y="414" width="92" height="48" rx="10" fill="#1e293b" stroke="#475569"/>
|
|
138
|
+
<text x="868" y="435" text-anchor="middle" class="label">AI clients</text>
|
|
139
|
+
<text x="868" y="453" text-anchor="middle" class="body">one or more</text>
|
|
140
|
+
<path d="M914 438H963" fill="none" stroke="#a78bfa" stroke-width="2.5" marker-end="url(#arrow-violet)"/>
|
|
141
|
+
<text x="939" y="428" text-anchor="middle" class="body">HTTP</text>
|
|
142
|
+
<rect x="969" y="414" width="169" height="48" rx="10" fill="#2e1065" stroke="#7c3aed"/>
|
|
143
|
+
<text x="1053.5" y="435" text-anchor="middle" class="label">Skillmux server</text>
|
|
144
|
+
<text x="1053.5" y="453" text-anchor="middle" class="body" style="font-size: 13px">Streamable HTTP /mcp</text>
|
|
145
|
+
|
|
146
|
+
<rect x="822" y="484" width="148" height="58" rx="10" fill="#2e1065" stroke="#7c3aed"/>
|
|
147
|
+
<text x="896" y="507" text-anchor="middle" class="label">Full image</text>
|
|
148
|
+
<text x="896" y="530" text-anchor="middle" class="body">GTE-small included</text>
|
|
149
|
+
<rect x="982" y="484" width="156" height="58" rx="10" fill="#1e293b" stroke="#475569"/>
|
|
150
|
+
<text x="1060" y="507" text-anchor="middle" class="label">Slim image</text>
|
|
151
|
+
<text x="1060" y="530" text-anchor="middle" class="body">remote or lexical</text>
|
|
152
|
+
|
|
153
|
+
<text x="822" y="570" class="body">Full image is the default deployment.</text>
|
|
154
|
+
</g>
|
|
155
|
+
|
|
156
|
+
<rect x="420" y="608" width="740" height="82" rx="14" fill="#1e293b"/>
|
|
157
|
+
<text x="444" y="633" class="chip" fill="#cbd5e1">MCP TOOL CONTRACT · STDIO + HTTP</text>
|
|
158
|
+
<text x="444" y="655" class="mono mono-light" style="font-size: 12px">resolve_skill → lexical + vector → RRF → optional rerank → top_k → ranked candidates</text>
|
|
159
|
+
<text x="444" y="677" class="mono mono-light" style="font-size: 12px">fetch_skill → current SKILL.md bytes + SHA-256</text>
|
|
160
|
+
</svg>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 720" role="img" aria-labelledby="title desc">
|
|
2
2
|
<title id="title">One vault source of truth, three ways to use Skillmux</title>
|
|
3
|
-
<desc id="desc">One Git-backed vault source of truth
|
|
3
|
+
<desc id="desc">One Git-backed vault source of truth holds one SKILL.md per child directory and feeds a client checkout and a server checkout. On a client machine, Skillmux CLI manages native skills and serves local stdio MCP; a server checkout serves shared Streamable HTTP MCP. resolve_skill fuses lexical and vector results and optionally reranks them; fetch_skill returns the current SKILL.md bytes with a SHA-256. Git and deployment own checkout replication and freshness.</desc>
|
|
4
4
|
|
|
5
5
|
<defs>
|
|
6
6
|
<filter id="shadow" x="-15%" y="-15%" width="130%" height="140%">
|
|
@@ -68,14 +68,14 @@
|
|
|
68
68
|
<text x="48" y="78" class="subtitle">Git and deployment replicate checkouts; Skillmux uses each checkout where it runs.</text>
|
|
69
69
|
|
|
70
70
|
<g filter="url(#shadow)">
|
|
71
|
-
<rect x="
|
|
72
|
-
<circle cx="
|
|
73
|
-
<path d="
|
|
74
|
-
<text x="
|
|
75
|
-
<text x="
|
|
76
|
-
<text x="
|
|
77
|
-
<rect x="
|
|
78
|
-
<text x="
|
|
71
|
+
<rect x="280" y="106" width="640" height="118" rx="18" fill="#ffffff" stroke="#cbd5e1" stroke-width="2"/>
|
|
72
|
+
<circle cx="324" cy="147" r="18" fill="#0f172a"/>
|
|
73
|
+
<path d="M314 141H327L333 147L327 153H314M320 135V159" fill="none" stroke="#ffffff" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
74
|
+
<text x="358" y="144" class="card-title">Git-backed vault source of truth</text>
|
|
75
|
+
<text x="358" y="172" class="mono">SKILL.md per child directory</text>
|
|
76
|
+
<text x="358" y="200" class="body">A checkout is a physical copy of it on one machine.</text>
|
|
77
|
+
<rect x="751" y="155" width="137" height="34" rx="9" fill="#f1f5f9" stroke="#cbd5e1"/>
|
|
78
|
+
<text x="819.5" y="177" text-anchor="middle" class="mono">skillmux.toml</text>
|
|
79
79
|
</g>
|
|
80
80
|
|
|
81
81
|
<path d="M520 224V252H410V277" fill="none" stroke="#0f766e" stroke-width="3" marker-end="url(#arrow-teal)"/>
|
|
@@ -87,11 +87,13 @@
|
|
|
87
87
|
<rect x="40" y="284" width="740" height="302" rx="18" fill="#ffffff" stroke="#99d5cc" stroke-width="2"/>
|
|
88
88
|
<rect x="62" y="306" width="124" height="26" rx="13" fill="#ccfbf1"/>
|
|
89
89
|
<text x="124" y="324" text-anchor="middle" class="chip" fill="#115e59">SKILLMUX CLI</text>
|
|
90
|
-
<text x="62" y="365" class="card-title">
|
|
91
|
-
<text x="62" y="390" class="body">
|
|
90
|
+
<text x="62" y="365" class="card-title">On one client machine</text>
|
|
91
|
+
<text x="62" y="390" class="body">Manage native skills, add local MCP retrieval, or do both.</text>
|
|
92
92
|
|
|
93
93
|
<rect x="62" y="414" width="276" height="48" rx="10" fill="#f0fdfa" stroke="#99d5cc"/>
|
|
94
|
-
<
|
|
94
|
+
<circle cx="85" cy="438" r="11" fill="#0f766e"/>
|
|
95
|
+
<text x="85" y="442.5" text-anchor="middle" style="font-size: 13px; font-weight: 750" fill="#ffffff">1</text>
|
|
96
|
+
<text x="200" y="433" text-anchor="middle" class="label" style="font-size: 17px">Manage native skills</text>
|
|
95
97
|
<text x="200" y="453" text-anchor="middle" class="mono">skillmux init · sync</text>
|
|
96
98
|
<path d="M200 462V487" fill="none" stroke="#0f766e" stroke-width="2.5" marker-end="url(#arrow-teal)"/>
|
|
97
99
|
<rect x="62" y="493" width="276" height="49" rx="10" fill="#f8fafc" stroke="#cbd5e1"/>
|
|
@@ -107,17 +109,19 @@
|
|
|
107
109
|
|
|
108
110
|
<g filter="url(#shadow)">
|
|
109
111
|
<rect x="420" y="414" width="338" height="128" rx="10" fill="#eff6ff" stroke="#93c5fd"/>
|
|
110
|
-
<
|
|
111
|
-
<text x="
|
|
112
|
-
|
|
113
|
-
<
|
|
114
|
-
|
|
115
|
-
<
|
|
116
|
-
<text x="
|
|
117
|
-
<
|
|
118
|
-
<text x="
|
|
119
|
-
<
|
|
120
|
-
<text x="
|
|
112
|
+
<circle cx="453" cy="435" r="11" fill="#2563eb"/>
|
|
113
|
+
<text x="453" y="439.5" text-anchor="middle" style="font-size: 13px; font-weight: 750" fill="#ffffff">2</text>
|
|
114
|
+
<text x="476" y="441" class="label" style="font-size: 17px">Add local MCP retrieval</text>
|
|
115
|
+
<text x="442" y="463" class="body">Reaches the whole indexed vault on demand.</text>
|
|
116
|
+
|
|
117
|
+
<rect x="442" y="475" width="92" height="48" rx="10" fill="#f8fafc" stroke="#cbd5e1"/>
|
|
118
|
+
<text x="488" y="505" text-anchor="middle" class="label">AI client</text>
|
|
119
|
+
<path d="M534 499H578" fill="none" stroke="#2563eb" stroke-width="2.5" marker-end="url(#arrow-blue)"/>
|
|
120
|
+
<text x="559" y="489" text-anchor="middle" class="body">stdio</text>
|
|
121
|
+
<rect x="584" y="470" width="152" height="62" rx="10" fill="#ffffff" stroke="#93c5fd"/>
|
|
122
|
+
<text x="660" y="492" text-anchor="middle" class="mono">skillmux serve</text>
|
|
123
|
+
<text x="660" y="511" text-anchor="middle" class="body">default: FTS5 +</text>
|
|
124
|
+
<text x="660" y="527" text-anchor="middle" class="body">local GTE-small</text>
|
|
121
125
|
|
|
122
126
|
</g>
|
|
123
127
|
|
|
@@ -125,17 +129,19 @@
|
|
|
125
129
|
<rect x="800" y="284" width="360" height="302" rx="18" fill="#ffffff" stroke="#c4b5fd" stroke-width="2"/>
|
|
126
130
|
<rect x="822" y="306" width="136" height="26" rx="13" fill="#ede9fe"/>
|
|
127
131
|
<text x="890" y="324" text-anchor="middle" class="chip" fill="#6d28d9">SKILLMUX SERVER</text>
|
|
128
|
-
<
|
|
132
|
+
<circle cx="833" cy="358" r="11" fill="#7c3aed"/>
|
|
133
|
+
<text x="833" y="362.5" text-anchor="middle" style="font-size: 13px; font-weight: 750" fill="#ffffff">3</text>
|
|
134
|
+
<text x="856" y="365" class="card-title">Run a shared MCP service</text>
|
|
129
135
|
<text x="822" y="390" class="body">Read a server checkout to serve several clients.</text>
|
|
130
136
|
|
|
131
|
-
<rect x="822" y="414" width="
|
|
132
|
-
<text x="
|
|
133
|
-
<text x="
|
|
134
|
-
<path d="
|
|
135
|
-
<text x="
|
|
136
|
-
<rect x="
|
|
137
|
-
<text x="
|
|
138
|
-
<text x="
|
|
137
|
+
<rect x="822" y="414" width="92" height="48" rx="10" fill="#f8fafc" stroke="#cbd5e1"/>
|
|
138
|
+
<text x="868" y="435" text-anchor="middle" class="label">AI clients</text>
|
|
139
|
+
<text x="868" y="453" text-anchor="middle" class="body">one or more</text>
|
|
140
|
+
<path d="M914 438H963" fill="none" stroke="#7c3aed" stroke-width="2.5" marker-end="url(#arrow-violet)"/>
|
|
141
|
+
<text x="939" y="428" text-anchor="middle" class="body">HTTP</text>
|
|
142
|
+
<rect x="969" y="414" width="169" height="48" rx="10" fill="#f5f3ff" stroke="#c4b5fd"/>
|
|
143
|
+
<text x="1053.5" y="435" text-anchor="middle" class="label">Skillmux server</text>
|
|
144
|
+
<text x="1053.5" y="453" text-anchor="middle" class="body" style="font-size: 13px">Streamable HTTP /mcp</text>
|
|
139
145
|
|
|
140
146
|
<rect x="822" y="484" width="148" height="58" rx="10" fill="#f5f3ff" stroke="#c4b5fd"/>
|
|
141
147
|
<text x="896" y="507" text-anchor="middle" class="label">Full image</text>
|
|
@@ -144,11 +150,11 @@
|
|
|
144
150
|
<text x="1060" y="507" text-anchor="middle" class="label">Slim image</text>
|
|
145
151
|
<text x="1060" y="530" text-anchor="middle" class="body">remote or lexical</text>
|
|
146
152
|
|
|
147
|
-
<text x="822" y="570" class="body">
|
|
153
|
+
<text x="822" y="570" class="body">Full image is the default deployment.</text>
|
|
148
154
|
</g>
|
|
149
155
|
|
|
150
156
|
<rect x="420" y="608" width="740" height="82" rx="14" fill="#0f172a"/>
|
|
151
157
|
<text x="444" y="633" class="chip" fill="#cbd5e1">MCP TOOL CONTRACT · STDIO + HTTP</text>
|
|
152
158
|
<text x="444" y="655" class="mono mono-light" style="font-size: 12px">resolve_skill → lexical + vector → RRF → optional rerank → top_k → ranked candidates</text>
|
|
153
|
-
<text x="444" y="677" class="mono mono-light" style="font-size: 12px">fetch_skill →
|
|
159
|
+
<text x="444" y="677" class="mono mono-light" style="font-size: 12px">fetch_skill → current SKILL.md bytes + SHA-256</text>
|
|
154
160
|
</svg>
|
|
Binary file
|
|
Binary file
|
package/docs/cli.md
CHANGED
|
@@ -21,10 +21,11 @@ or [Managing skills](skill-management.md).
|
|
|
21
21
|
|
|
22
22
|
The Docker image is a shared-server runtime, not a replacement for the host
|
|
23
23
|
CLI. Its `skillmux --help` surface is intentionally limited to `serve`,
|
|
24
|
-
`index`, `doctor`, `report`, `
|
|
25
|
-
inspection (`show`, `get`, `validate`,
|
|
26
|
-
`install`, pinning, `sync`, project or
|
|
27
|
-
|
|
24
|
+
`index`, `doctor`, `report`, `audit prune`, `eval promote`, `scan`,
|
|
25
|
+
`skill which`, and read-only `config` inspection (`show`, `get`, `validate`,
|
|
26
|
+
`diff`, and `status`). Run `init`, `install`, pinning, `sync`, project or
|
|
27
|
+
target management, model downloads, contexts, and bare `eval` (vault ranking
|
|
28
|
+
evaluation, which needs local embeddings and the vault) on the host.
|
|
28
29
|
|
|
29
30
|
When the image rejects one of those commands, it exits with code 2. JSON mode
|
|
30
31
|
uses `CONTAINER_COMMAND_UNSUPPORTED` and includes `rejected_command`,
|
|
@@ -247,7 +248,7 @@ command prints the preserved path so cleanup remains an explicit user action.
|
|
|
247
248
|
|
|
248
249
|
## Core skills (`skillmux core`)
|
|
249
250
|
|
|
250
|
-
Pin or unpin skills into `[core]
|
|
251
|
+
Pin or unpin skills into `[core]`, the tier every target receives by
|
|
251
252
|
default, capped at 25 skills:
|
|
252
253
|
|
|
253
254
|
```sh
|
|
@@ -287,6 +288,63 @@ skillmux skill which csv-formatter
|
|
|
287
288
|
|
|
288
289
|
---
|
|
289
290
|
|
|
291
|
+
## Observability and evaluation (`skillmux report`, `audit`, `eval`)
|
|
292
|
+
|
|
293
|
+
`resolve_skill` records every request to an audit log; `fetch_skill` records
|
|
294
|
+
what was actually opened and, when the caller passes back the `request_id`
|
|
295
|
+
from a prior resolve, correlates the fetch to that resolve and its rank in
|
|
296
|
+
the shortlist. `skillmux report` summarizes this data, `skillmux audit prune`
|
|
297
|
+
reclaims space, and `skillmux eval promote` turns correlated fetches into
|
|
298
|
+
eval cases.
|
|
299
|
+
|
|
300
|
+
```sh
|
|
301
|
+
# Summarize activity from the local state or a remote server
|
|
302
|
+
skillmux report --since 7d
|
|
303
|
+
skillmux report --server https://skillmux.internal:3000 --since 24h
|
|
304
|
+
skillmux report --db ~/.local/state/skillmux/audit.sqlite3 --since 2026-08-01
|
|
305
|
+
|
|
306
|
+
# Prune audit rows older than the configured retention window (default 90 days)
|
|
307
|
+
skillmux audit prune --yes
|
|
308
|
+
skillmux audit prune --older-than 30d --dry-run
|
|
309
|
+
skillmux audit prune --older-than 30d --json
|
|
310
|
+
|
|
311
|
+
# Promote observed, correlated fetches into an eval case file
|
|
312
|
+
skillmux eval promote --since 7d --dry-run
|
|
313
|
+
skillmux eval promote --since 7d --yes
|
|
314
|
+
skillmux eval promote --since 7d --target eval/observed.json --yes
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
`report` reads `--server <url>`, `--db <path>` (an explicit SQLite file,
|
|
318
|
+
opened read-only), or the configured local `state_dir` by default;
|
|
319
|
+
`--server` and `--db` are mutually exclusive. Alongside request totals,
|
|
320
|
+
empty-shortlist rate, retrieval-lane totals, degradation counts, and
|
|
321
|
+
per-skill candidate counts, `report` prints an acceptance signal derived
|
|
322
|
+
from correlated fetches: `acceptance_rate`, `observed_mrr` (reciprocal rank
|
|
323
|
+
of the first fetched candidate), and `top1_acceptance_rate`, each computed
|
|
324
|
+
over resolves that returned at least one candidate. When a window has no
|
|
325
|
+
correlated fetches, `report` marks the signal `unavailable` and states the
|
|
326
|
+
uncorrelated fetch count instead of printing a misleading `0.000`. It also
|
|
327
|
+
lists the top queries that returned candidates but received no correlated
|
|
328
|
+
fetch, distinct from the existing top empty-shortlist list.
|
|
329
|
+
|
|
330
|
+
`audit prune` deletes resolve and fetch rows older than `--older-than` (same
|
|
331
|
+
window syntax as `--since`), or `audit.retention_days` from configuration
|
|
332
|
+
(default 90; `0` disables pruning). `--dry-run` reports counts without
|
|
333
|
+
writing. Non-interactive runs require `--yes`. The server also prunes
|
|
334
|
+
automatically once at startup and at most once per 24 hours while running;
|
|
335
|
+
manual pruning is for on-demand cleanup or a tighter window.
|
|
336
|
+
|
|
337
|
+
`eval promote` reads correlated fetches since `--since`, deduplicates them by
|
|
338
|
+
normalized query, and writes `{ query, split: "observed", relevant_skill_ids
|
|
339
|
+
}` cases to `--target` (default an `eval-observed.json` file under
|
|
340
|
+
`state_dir`; never the hand-curated `eval/queries.json` unless given
|
|
341
|
+
explicitly). It never rewrites a case for a query already present in the
|
|
342
|
+
target file; skipped counts are reported in the summary. Because promoted
|
|
343
|
+
cases carry raw user queries, `eval promote` always prints a stderr warning.
|
|
344
|
+
Both `--dry-run` and `--yes` behave as elsewhere in the CLI.
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
290
348
|
## Administrative HTTP API (`/admin/v1/*`)
|
|
291
349
|
|
|
292
350
|
The HTTP server has two separate surfaces:
|
package/docs/concepts.md
CHANGED
|
@@ -63,6 +63,16 @@ checkout over HTTP.
|
|
|
63
63
|
|
|
64
64
|
## Deployment topologies
|
|
65
65
|
|
|
66
|
+
```mermaid
|
|
67
|
+
flowchart TD
|
|
68
|
+
V[Git-backed vault source of truth]
|
|
69
|
+
V -->|client checkout| CLI[Skillmux CLI]
|
|
70
|
+
V -->|server checkout| SRV[Skillmux server]
|
|
71
|
+
CLI --> NM[Native management: filesystem links]
|
|
72
|
+
CLI --> LM[Local MCP: stdio]
|
|
73
|
+
SRV --> SM[Shared MCP: Streamable HTTP]
|
|
74
|
+
```
|
|
75
|
+
|
|
66
76
|
| Topology | Process location | Transport | Typical installation |
|
|
67
77
|
| --- | --- | --- | --- |
|
|
68
78
|
| Native management | Client machine | Filesystem links | Skillmux CLI |
|
package/docs/configuration.md
CHANGED
|
@@ -203,9 +203,9 @@ enabled = false
|
|
|
203
203
|
token_env = "SKILLMUX_ADMIN_TOKEN"
|
|
204
204
|
```
|
|
205
205
|
|
|
206
|
-
Defaults are loopback-only (`hostname = "127.0.0.1"`) with CORS deny-by-default (`allowed_origins = []`)
|
|
206
|
+
Defaults are loopback-only (`hostname = "127.0.0.1"`) with CORS deny-by-default (`allowed_origins = []`), so a zero-config `skillmux serve --transport http` is not reachable from the network or from a browser tab on another origin. Docker sets `hostname` to `0.0.0.0` automatically (`RUNNING_IN_DOCKER=true`) since port-mapping needs the container to accept connections on all interfaces.
|
|
207
207
|
|
|
208
|
-
Before exposing HTTP beyond localhost, set `hostname` to a reachable interface, `auth_enabled = true` with a token, and populate `allowed_origins` with the specific origins that need browser access. `rate_limit.trust_proxy` should stay `false` unless a trusted reverse proxy sets `X-Forwarded-For
|
|
208
|
+
Before exposing HTTP beyond localhost, set `hostname` to a reachable interface, `auth_enabled = true` with a token, and populate `allowed_origins` with the specific origins that need browser access. `rate_limit.trust_proxy` should stay `false` unless a trusted reverse proxy sets `X-Forwarded-For`: it's otherwise a client-controlled, spoofable header, and trusting it defeats per-client rate limiting.
|
|
209
209
|
|
|
210
210
|
`server.auth_token_env` names the MCP token for AI clients calling `/mcp`.
|
|
211
211
|
`server.admin.token_env` names a distinct administrative token for operators
|
|
@@ -242,13 +242,13 @@ skills = ["pdf-extractor"] # must not overlap [core]
|
|
|
242
242
|
[targets.claude-code]
|
|
243
243
|
dir = "/Users/you/.claude/skills"
|
|
244
244
|
host = "workhorse" # optional; init adds the current hostname
|
|
245
|
-
project_groups = ["repo1"] # which [project.*] groups materialize into this target
|
|
245
|
+
project_groups = ["repo1"] # which [project.*] groups materialize into this target; [] means none
|
|
246
246
|
```
|
|
247
247
|
|
|
248
|
-
- `[core].skills
|
|
249
|
-
- `[project.<group>].skills
|
|
250
|
-
- `[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"]`)
|
|
251
|
-
- `[targets.<name>]
|
|
248
|
+
- `[core].skills`: symlinked into every `[targets.*]` dir on `sync`. Capped at 25 skills; `sync` fails if a listed skill id isn't actually in the vault.
|
|
249
|
+
- `[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.
|
|
250
|
+
- `[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.
|
|
251
|
+
- `[targets.<name>]`: one entry per adopted surface. `skillmux init --target <name> --yes` writes these and scopes newly added targets to the current hostname. Hand-editing is fine as long as `sync` is still allowed to own the directory (see below). 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.
|
|
252
252
|
|
|
253
253
|
**Pin/unpin without hand-editing.** `skillmux core pin`/`unpin` mutate `[core]` for you, and `skillmux project pin`/`unpin` mutate `[project.*]`, validating with the same rules `sync` enforces (skill must resolve from `vault_path`, no duplicate pins, `[core]` stays under the 25-skill cap) before writing anything:
|
|
254
254
|
|
|
@@ -261,16 +261,16 @@ skillmux core unpin csv-formatter pdf-extractor --yes # unpin
|
|
|
261
261
|
skillmux project unpin repo1 pdf-extractor --yes # remove from a group (group stays, even if empty)
|
|
262
262
|
```
|
|
263
263
|
|
|
264
|
-
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
|
|
264
|
+
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.
|
|
265
265
|
|
|
266
|
-
> **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
|
|
266
|
+
> **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.
|
|
267
267
|
>
|
|
268
268
|
> **Breaking change:** `[targets.<name>].project` (a boolean) has been replaced by `project_groups` (an array of `[project.*]` names). A manifest still using the old field fails to parse with an error pointing at the new one. To migrate, replace `project = true` with `project_groups = [...]` listing every group that target previously received (previously *all* groups, unconditionally); replace `project = false` with `project_groups = []`.
|
|
269
269
|
>
|
|
270
|
-
> **Breaking change:** `[project.<group>].repos` has been renamed to `paths
|
|
270
|
+
> **Breaking change:** `[project.<group>].repos` has been renamed to `paths`. It was never required to be a git repository, just a local directory, and the old name collided in meaning with `skillmux install <repo>`'s unrelated git-source `repo` concept. A manifest still using `repos` fails to parse with an error pointing at `paths`; migrate by renaming the key (values are unchanged).
|
|
271
271
|
|
|
272
272
|
Every `[core]`/`[project.*]` skill_id must resolve from the configured
|
|
273
|
-
`vault_path` checkout
|
|
273
|
+
`vault_path` checkout. Pinning a skill that only exists in a
|
|
274
274
|
`local_vault_paths` entry (see below) fails `sync` with a distinct error, since
|
|
275
275
|
the manifest is meant to be portable across machines and a machine-local
|
|
276
276
|
override wouldn't exist elsewhere. `doctor` validates the manifest as part of
|
|
@@ -286,7 +286,7 @@ Skillmux created. Sync removes only those tracked entries, preserves unrelated
|
|
|
286
286
|
content, and rejects a desired skill that collides with an unmanaged entry
|
|
287
287
|
before changing anything.
|
|
288
288
|
|
|
289
|
-
`sync` refuses to touch a directory that exists but has no marker
|
|
289
|
+
`sync` refuses to touch a directory that exists but has no marker; run
|
|
290
290
|
`skillmux init --target <name> --yes` first, which either creates the
|
|
291
291
|
directory fresh or adopts an existing one in place (contents untouched).
|
|
292
292
|
`sync --restore-monolith` likewise refuses a `local_vault` marker or any
|
|
@@ -302,34 +302,34 @@ cannot be inferred.
|
|
|
302
302
|
|
|
303
303
|
### Local vault overlays
|
|
304
304
|
|
|
305
|
-
`local_vault_paths` (in `config.toml`, alongside `vault_path`) lets one machine layer override-only skills on top of the shared vault
|
|
305
|
+
`local_vault_paths` (in `config.toml`, alongside `vault_path`) lets one machine layer override-only skills on top of the shared vault (a skill being authored locally, a machine-specific script, or a patched copy of an upstream skill) without touching `vault_path` itself:
|
|
306
306
|
|
|
307
307
|
```toml
|
|
308
308
|
vault_path = "~/skills" # configured checkout; owns skillmux.toml and the sync git hook
|
|
309
309
|
local_vault_paths = ["~/skills-local"] # optional, default []: override-only, checked first
|
|
310
310
|
```
|
|
311
311
|
|
|
312
|
-
- **Resolution order**: for any given `skill_id`, `local_vault_paths` entries are checked first, in array order; `vault_path` is the fallback. This applies everywhere a skill's on-disk location matters
|
|
312
|
+
- **Resolution order**: for any given `skill_id`, `local_vault_paths` entries are checked first, in array order; `vault_path` is the fallback. This applies everywhere a skill's on-disk location matters: indexing, `resolve_skill`/`fetch_skill` delivery, and `sync`'s symlink target.
|
|
313
313
|
- **`vault_path` keeps its exact existing meaning.** `skillmux.toml` and the `sync --install-hook` git hook only ever live in `vault_path`; `skillmux doctor` warns if it finds a stray manifest inside a `local_vault_paths` entry instead.
|
|
314
|
-
- **`[core]`/`[project.*]` pins must resolve from `vault_path`.** Since the manifest is meant to be portable, `sync`/`doctor` reject a pin backed only by a `local_vault_paths` entry
|
|
314
|
+
- **`[core]`/`[project.*]` pins must resolve from `vault_path`.** Since the manifest is meant to be portable, `sync`/`doctor` reject a pin backed only by a `local_vault_paths` entry; see the manifest section above.
|
|
315
315
|
- **Not yet covered**: `startVaultWatcher`'s live filesystem watch still only watches `vault_path`; a change inside a `local_vault_paths` entry is picked up lazily (on the next `resolve_skill`/`fetch_skill`/`sync` call, via the same mtime staleness check `vault_path` already uses), not instantly.
|
|
316
316
|
|
|
317
|
-
**Visibility.** A `skill_id` present in more than one root is silently resolved via the precedence above with no output during normal use
|
|
317
|
+
**Visibility.** A `skill_id` present in more than one root is silently resolved via the precedence above with no output during normal use. Two commands make that resolution visible on demand:
|
|
318
318
|
|
|
319
|
-
- `skillmux skill which <skill_id
|
|
319
|
+
- `skillmux skill which <skill_id>`: prints which root actually serves that skill, and names every root it shadows:
|
|
320
320
|
```
|
|
321
321
|
$ skillmux skill which my-skill
|
|
322
322
|
my-skill: serving from /home/user/skills-local
|
|
323
323
|
shadows: /home/user/skills
|
|
324
324
|
```
|
|
325
325
|
Exits non-zero with `<skill_id>: not found in vault_path or local_vault_paths` if no root has it.
|
|
326
|
-
- `skillmux doctor` reports every shadowed skill_id as an informational check (`shadowed:<skill_id>`, always `ok`) alongside its existing vault/manifest/embedding checks
|
|
326
|
+
- `skillmux doctor` reports every shadowed skill_id as an informational check (`shadowed:<skill_id>`, always `ok`) alongside its existing vault/manifest/embedding checks, so a scan of `doctor` output surfaces every override in one place, not just the one you thought to ask about.
|
|
327
327
|
|
|
328
|
-
**Discoverability.** A `local_vault_paths` entry is otherwise just a bare directory
|
|
328
|
+
**Discoverability.** A `local_vault_paths` entry is otherwise just a bare directory. Nothing on disk says it belongs to skillmux or which `vault_path` it overlays. `skillmux local-vault init <path>` writes a `.skillmux` marker recording that relationship:
|
|
329
329
|
|
|
330
330
|
```sh
|
|
331
331
|
skillmux local-vault init ~/skills-local
|
|
332
332
|
# wrote /home/user/skills-local/.skillmux (role: local_vault, vault_path: /home/user/skills)
|
|
333
333
|
```
|
|
334
334
|
|
|
335
|
-
`<path>` must already be one of the configured `local_vault_paths` entries and must exist on disk
|
|
335
|
+
`<path>` must already be one of the configured `local_vault_paths` entries and must exist on disk; the command only ever writes the marker, it never adds the path to `config.toml` for you. `skillmux doctor` reports each entry's marker status (`local_vault_marker:<path>`): `ok: false` if no marker exists yet (with the exact `local-vault init` command to fix it), or if the marker's recorded `vault_path` no longer matches the one currently configured (drift: e.g. after copying the directory to a machine with a different `vault_path`).
|