@hasna/skills 0.2.1 → 0.4.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/README.md +192 -44
- package/bin/index.js +15778 -24369
- package/bin/mcp.js +4802 -13678
- package/bin/migrate.js +5 -0
- package/bin/server.js +380 -214
- package/bin/worker.js +365 -199
- package/dist/admin-contract.d.ts +5861 -916
- package/dist/admin-contract.js +3611 -13914
- package/dist/cli/cli.test-utils.d.ts +14 -0
- package/dist/cli/commands/remote-account.d.ts +7 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +5543 -14354
- package/dist/lib/api-url.d.ts +32 -23
- package/dist/lib/auth-store.d.ts +111 -42
- package/dist/lib/config.d.ts +19 -21
- package/dist/lib/feedback.d.ts +8 -3
- package/dist/lib/fleet-credentials.d.ts +252 -0
- package/dist/lib/instance-credentials-race.fixture.d.ts +1 -0
- package/dist/lib/instance-credentials.d.ts +13 -0
- package/dist/lib/mcp-contracts.d.ts +4 -0
- package/dist/lib/portable-skills-files.d.ts +4 -0
- package/dist/lib/portable-skills-types.d.ts +2 -0
- package/dist/lib/remote-account.d.ts +42 -0
- package/dist/lib/remote-auth.d.ts +32 -0
- package/dist/lib/remote-client.d.ts +75 -10
- package/dist/lib/remote-customer-operations.d.ts +106 -0
- package/dist/lib/remote-files.d.ts +21 -0
- package/dist/lib/remote-registry.d.ts +31 -11
- package/dist/lib/run-routing.d.ts +7 -4
- package/dist/lib/run-state.d.ts +3 -0
- package/dist/lib/vendor-host-policy.d.ts +31 -0
- package/dist/mcp/remote-customer-tools.d.ts +2 -0
- package/dist/sdk/index.d.ts +10 -0
- package/dist/sdk/index.js +6251 -14621
- package/dist/sdk/runs.d.ts +101 -19
- package/dist/storage.js +9 -14
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Skills library for AI coding agents — discover, pin, and run reusable capabili
|
|
|
11
11
|
bun install -g @hasna/skills
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
Requires [Bun](https://bun.sh/) 1.
|
|
14
|
+
Requires [Bun](https://bun.sh/) 1.3+.
|
|
15
15
|
|
|
16
16
|
## Quick Start
|
|
17
17
|
|
|
@@ -19,11 +19,12 @@ Requires [Bun](https://bun.sh/) 1.0+.
|
|
|
19
19
|
# Browse skills interactively
|
|
20
20
|
skills
|
|
21
21
|
|
|
22
|
-
#
|
|
23
|
-
|
|
24
|
-
skills
|
|
22
|
+
# Sign in. With a credential and no URL, the CLI talks to the fleet gateway;
|
|
23
|
+
# point it at your own instance first if you run one.
|
|
24
|
+
skills setup --api-url https://skills.example.com # only for your own instance
|
|
25
|
+
skills auth login --api-key "$HASNA_SKILLS_API_KEY"
|
|
25
26
|
|
|
26
|
-
# With no
|
|
27
|
+
# With no credential and no URL, skills simply run on this machine
|
|
27
28
|
skills list
|
|
28
29
|
|
|
29
30
|
# Optionally pin a skill preference in this project
|
|
@@ -54,21 +55,16 @@ create local run metadata, and then expose status and artifact commands. They
|
|
|
54
55
|
do not fall back to bundled local execution when auth is missing or the server
|
|
55
56
|
runtime is unavailable.
|
|
56
57
|
|
|
57
|
-
Routing is
|
|
58
|
-
only when
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
API is configured. No skill in the OSS catalog is server-owned today; the
|
|
58
|
+
Routing is credential-driven and local is the default: a run is sent to the API
|
|
59
|
+
only when a credential resolves (see **Credentials** below) and the skill carries
|
|
60
|
+
the server-owned marker. Every other skill runs on this machine, whether or not
|
|
61
|
+
a credential exists. No skill in the OSS catalog is server-owned today; the
|
|
62
62
|
marker arrives with skills synced from a Skills API deployment. A server-owned
|
|
63
|
-
skill run without
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
Use `SKILLS_API_KEY` or `skills auth login --api-key` for server-side
|
|
67
|
-
execution:
|
|
63
|
+
skill run without a credential fails closed with an error naming the missing
|
|
64
|
+
setup — it never silently runs locally.
|
|
68
65
|
|
|
69
66
|
```bash
|
|
70
|
-
skills
|
|
71
|
-
skills auth login --api-key "$SKILLS_API_KEY"
|
|
67
|
+
skills auth login --api-key "$HASNA_SKILLS_API_KEY"
|
|
72
68
|
skills run <server-owned-skill> --brief "minimal geometric owl mark"
|
|
73
69
|
skills runs status <run-id>
|
|
74
70
|
skills exports download <run-id>
|
|
@@ -78,11 +74,73 @@ Browser/device-code and email-code login commands are retained for compatible
|
|
|
78
74
|
deployments. A Skills deployment can bootstrap with a provisioned API key via
|
|
79
75
|
`skills auth login --api-key`.
|
|
80
76
|
|
|
81
|
-
`
|
|
77
|
+
`HASNA_SKILLS_API_KEY` is the Skills API credential. It is not a provider
|
|
82
78
|
credential. Provider keys such as `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or
|
|
83
79
|
`GEMINI_API_KEY` remain supported only for free/local OSS skills whose
|
|
84
80
|
requirements explicitly document local provider use.
|
|
85
81
|
|
|
82
|
+
## Credentials
|
|
83
|
+
|
|
84
|
+
The credential and the service address are resolved by the shared client in
|
|
85
|
+
[`@hasna/contracts`](https://www.npmjs.com/package/@hasna/contracts), the same
|
|
86
|
+
ladder every Hasna CLI uses. Nothing here is resolved twice, and this package
|
|
87
|
+
keeps no credential store of its own.
|
|
88
|
+
|
|
89
|
+
**The credential, in precedence order, resolved fresh on every call:**
|
|
90
|
+
|
|
91
|
+
| # | Tier | Where |
|
|
92
|
+
|---|------|-------|
|
|
93
|
+
| 1 | Explicit argument | `--api-key`, `--profile` |
|
|
94
|
+
| 2 | Deliberate env pointer | `HASNA_SKILLS_API_KEY_OVERRIDE`, `HASNA_PROFILE`, `HASNA_SKILLS_API_KEY_REF` (a secrets-vault item key, never a value) |
|
|
95
|
+
| 3 | macOS Keychain | generic-password item `hasna.credentials.skills.api-key`, account `$HASNA_STATION`, else `hostname -s`, else `$USER` |
|
|
96
|
+
| 4 | Disk | `~/.hasna/skills/config/credentials` (mode 0400/0600; `HASNA_HOME` and `HASNA_CONFIG_HOME` relocate it; XDG is never consulted) |
|
|
97
|
+
| 5 | Environment | `HASNA_SKILLS_API_KEY` — a legitimate tier, and deliberately *below* disk |
|
|
98
|
+
|
|
99
|
+
Tier 5 sits below disk on purpose. A wrapper that injects `HASNA_SKILLS_API_KEY`
|
|
100
|
+
into one child process re-reads its store every time and cannot go stale; a shell
|
|
101
|
+
`export` can, and after a key rotation the file on disk is the correct one.
|
|
102
|
+
|
|
103
|
+
`skills auth login` writes tier 4. A tier an operator set on purpose (1 and 2)
|
|
104
|
+
never falls through to another identity: if it cannot be honoured, the command
|
|
105
|
+
fails rather than acting as a different principal.
|
|
106
|
+
|
|
107
|
+
`HASNA_SKILLS_API_KEY_REF` names a *vault item*, not a key, so it resolves in two
|
|
108
|
+
steps: the item is fetched through the `@hasna/secrets` SDK on each call, which
|
|
109
|
+
means a rotated item is picked up without a restart — and which means the SDK has
|
|
110
|
+
to be installed in the process. Every way that fetch can fail (SDK absent, vault
|
|
111
|
+
unreachable, item missing or empty) is terminal and exits non-zero; a pointer
|
|
112
|
+
never falls through to another tier, and never to the local corpus.
|
|
113
|
+
|
|
114
|
+
**The service address, in the same shape:**
|
|
115
|
+
|
|
116
|
+
`HASNA_SKILLS_API_URL` → the Keychain item `hasna.credentials.skills.api-url` →
|
|
117
|
+
`~/.hasna/skills/config/credentials` → the fleet gateway
|
|
118
|
+
`https://api.hasna.com/skills`. The gateway default applies only once a
|
|
119
|
+
credential has resolved, so an install with no credential names no host at all.
|
|
120
|
+
`skills setup --api-url <origin>` writes the credentials file; the address is
|
|
121
|
+
per-user, never per-project.
|
|
122
|
+
|
|
123
|
+
The unprefixed `SKILLS_API_KEY` and `SKILLS_API_URL` spellings are still accepted
|
|
124
|
+
as silent aliases one rung below the canonical names, for one release. Use the
|
|
125
|
+
`HASNA_`-prefixed names. `SKILL_API_KEY` (singular) is no longer read at all.
|
|
126
|
+
|
|
127
|
+
**Three outcomes, and no fourth:**
|
|
128
|
+
|
|
129
|
+
- a credential resolves → **hosted**, against the configured URL or the gateway.
|
|
130
|
+
A credential that resolves but cannot produce a usable key — a deliberate
|
|
131
|
+
selection that cannot be honoured, a vault pointer whose item is missing, any
|
|
132
|
+
tier that yields a blank value — is a **loud failure** too, never a demotion;
|
|
133
|
+
- no credential but a URL is configured → **loud failure**, exit non-zero. There
|
|
134
|
+
is no local fallback: answering from the bundled corpus while authentication is
|
|
135
|
+
unconfigured is a false green;
|
|
136
|
+
- neither → **local**. Skills ships its corpus, so running on this machine is a
|
|
137
|
+
real mode; it prints one line on stderr saying so.
|
|
138
|
+
|
|
139
|
+
The retired locations are not read: `auth.json` (in either the app directory or
|
|
140
|
+
the legacy `~/.skills/`), the old fleet-env and per-machine cloud env folders
|
|
141
|
+
under `~/.hasna`, and the XDG config directory. `~/.hasna` is a closed namespace
|
|
142
|
+
of app folders, and `XDG_CONFIG_HOME` is not consulted at all.
|
|
143
|
+
|
|
86
144
|
## CLI Commands
|
|
87
145
|
|
|
88
146
|
| Command | Alias | Description |
|
|
@@ -117,12 +175,12 @@ requirements explicitly document local provider use.
|
|
|
117
175
|
| `skills billing status` | | Show server account plan and balance |
|
|
118
176
|
| `skills billing checkout` | | Create a checkout session when billing is enabled |
|
|
119
177
|
| `skills billing portal` | | Create a customer portal session when billing is enabled |
|
|
120
|
-
| `skills credits buy <
|
|
178
|
+
| `skills credits buy <pack-id>` | | Create a credit-pack checkout session when billing is enabled |
|
|
121
179
|
| `skills setup-info` | | Version, pinned skills, agent configs, paths |
|
|
122
180
|
| `skills export` | | Export pinned skills as JSON |
|
|
123
181
|
| `skills import <file>` | | Pin skills from a JSON export |
|
|
124
182
|
| `skills config set <key> <value>` | | Set default agent, scope, output format, or API origin |
|
|
125
|
-
| `skills config unset <key>` | | Remove a configuration value (`skills config unset apiUrl` returns to running on this machine) |
|
|
183
|
+
| `skills config unset <key>` | | Remove a configuration value (`skills config unset apiUrl` clears the stored service address and returns to running on this machine) |
|
|
126
184
|
| `skills new <name>` | `scaffold` | Scaffold a portable skill under `~/.hasna/skills/installed/<name>` |
|
|
127
185
|
| `skills port <path>` | `add` | Import an existing skill folder into the portable standard |
|
|
128
186
|
| `skills create <name>` | | Scaffold a new custom skill directory |
|
|
@@ -146,7 +204,7 @@ requirements explicitly document local provider use.
|
|
|
146
204
|
- `--brief` — One-line format
|
|
147
205
|
- `--limit <n>` — Cap human rows where supported; use `--limit all` or `--limit 0` for every row
|
|
148
206
|
- `--cursor <n>` — Continue human-output pagination from a numeric offset
|
|
149
|
-
- `--remote` — Read browse/search data from
|
|
207
|
+
- `--remote` — Read browse/search data from the configured Skills instance (see **Credentials**)
|
|
150
208
|
- `--dry-run` — Preview without applying changes
|
|
151
209
|
- `--verbose` — Debug logging globally; richer human discovery rows where supported
|
|
152
210
|
- `--no-color` — Disable ANSI colors
|
|
@@ -206,15 +264,16 @@ Stable command shapes:
|
|
|
206
264
|
## Remote Registry
|
|
207
265
|
|
|
208
266
|
The npm package ships no bundled skill corpus. Discovery reads the local corpus
|
|
209
|
-
cache (`~/.hasna/skills/installed`, filled by `skills pull`) and, when
|
|
210
|
-
|
|
211
|
-
browse/search commands
|
|
212
|
-
|
|
267
|
+
cache (`~/.hasna/skills/installed`, filled by `skills pull`) and, when a
|
|
268
|
+
credential resolves, the server's registry. This is not a mode you select:
|
|
269
|
+
whether browse/search commands read a server's registry is one fact, whether a
|
|
270
|
+
credential resolves (see [Credentials](#credentials)). To point at your own
|
|
271
|
+
instance:
|
|
213
272
|
|
|
214
273
|
```bash
|
|
215
|
-
export
|
|
216
|
-
# or persist it:
|
|
217
|
-
skills
|
|
274
|
+
export HASNA_SKILLS_API_URL=https://your-server.example
|
|
275
|
+
# or persist it in the credentials file the shared ladder reads:
|
|
276
|
+
skills setup --api-url https://your-server.example
|
|
218
277
|
# and to stop using it:
|
|
219
278
|
skills config unset apiUrl
|
|
220
279
|
|
|
@@ -228,8 +287,9 @@ If the URL is an origin such as `https://your-server.example`, the CLI requests
|
|
|
228
287
|
`/api/v1/skills`. If it already ends in `/api` or `/api/v1`, the CLI appends
|
|
229
288
|
`/skills`.
|
|
230
289
|
|
|
231
|
-
Authenticated registry listing and premium server-side execution use
|
|
232
|
-
|
|
290
|
+
Authenticated registry listing and premium server-side execution use whichever
|
|
291
|
+
credential the ladder resolves — most often the one saved by
|
|
292
|
+
`skills auth login --api-key`.
|
|
233
293
|
|
|
234
294
|
The typed `RemoteSkillsClient` also exposes pin, tag, and cursor-based
|
|
235
295
|
incremental-sync methods (`listPins`/`pin`/`unpin`, `listTags`/`skillsByTag`,
|
|
@@ -306,16 +366,100 @@ skills mcp --register all # Register with all supported agents
|
|
|
306
366
|
|
|
307
367
|
## Skills API
|
|
308
368
|
|
|
369
|
+
Use a named profile for each independently operated instance. A commercial Skills instance
|
|
370
|
+
and an internal instance have separate credentials, accounts,
|
|
371
|
+
credits and data. Selecting one does not change another profile or the fleet
|
|
372
|
+
resolver's existing defaults.
|
|
373
|
+
|
|
309
374
|
```bash
|
|
310
|
-
|
|
311
|
-
skills
|
|
312
|
-
skills
|
|
375
|
+
# Configure the commercial instance before signing in.
|
|
376
|
+
skills --profile customer setup --api-url https://skills.example.com/api/v1 --json
|
|
377
|
+
skills --profile customer auth signup --email you@example.com --json
|
|
378
|
+
skills --profile customer auth login --email you@example.com --code <CODE> --json
|
|
379
|
+
skills --profile customer auth whoami --json
|
|
380
|
+
skills --profile customer capabilities --json
|
|
381
|
+
skills --profile customer list --remote --json
|
|
382
|
+
|
|
383
|
+
# Quote without spending. Put CLI flags before the skill name.
|
|
384
|
+
skills --profile customer quote --json blog-article --topic "Your topic"
|
|
385
|
+
skills --profile customer run --remote --yes --wait --json --idempotency-key article-001 blog-article --topic "Your topic"
|
|
386
|
+
skills --profile customer runs status <run-id> --json
|
|
387
|
+
skills --profile customer runs logs <run-id> --json
|
|
388
|
+
skills --profile customer runs artifacts <run-id> --json
|
|
389
|
+
skills --profile customer exports download <run-id> --json
|
|
390
|
+
|
|
391
|
+
skills --profile customer billing status --json
|
|
392
|
+
skills --profile customer billing usage --json
|
|
393
|
+
skills --profile customer billing invoices --json
|
|
394
|
+
skills --profile customer credits packs --json
|
|
395
|
+
skills --profile customer credits buy <pack-id> --json
|
|
396
|
+
skills --profile customer billing portal --json
|
|
397
|
+
skills --profile customer auth keys list --email you@example.com --code <FRESH-CODE> --json
|
|
398
|
+
# Request a fresh OTP, then create a separately scoped key (shown once).
|
|
399
|
+
skills --profile customer auth signup --email you@example.com --json
|
|
400
|
+
skills --profile customer auth keys create automation --email you@example.com --code <CODE> --scope runs:read --json
|
|
401
|
+
skills --profile customer auth logout --json
|
|
313
402
|
```
|
|
314
403
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
404
|
+
An origin, a full `/api/v1` base and a base with a path prefix normalize to the
|
|
405
|
+
same routes. `HASNA_PROFILE=customer` selects the same profile as `--profile`.
|
|
406
|
+
`HASNA_SKILLS_API_URL` (or the compatible `SKILLS_API_URL`) is an explicit URL
|
|
407
|
+
override, not permission to send a saved key to a different instance. Stored
|
|
408
|
+
keys retain their original instance binding; sign in to a separate profile to
|
|
409
|
+
switch instances. `HASNA_HOME` / `HASNA_CONFIG_HOME` isolate credential state;
|
|
410
|
+
`HASNA_SKILLS_DIR` separately isolates corpus/configuration data. They do not
|
|
411
|
+
require changing `HOME`.
|
|
412
|
+
|
|
413
|
+
A paid remote run requires explicit approval. Interactive runs ask before
|
|
414
|
+
submission; JSON and other noninteractive runs require `--yes`. The approved
|
|
415
|
+
quote becomes the server-enforced credit ceiling. A changed price above that
|
|
416
|
+
ceiling fails before admission. A compatible server must advertise bounded
|
|
417
|
+
approval; older or unsupported APIs return errors, not local results. Reuse the
|
|
418
|
+
same idempotency key only for an identical submission to safely recover an
|
|
419
|
+
interrupted response. `runs cancel` and `runs resume` call the server's lifecycle
|
|
420
|
+
operations and can be refused when the current state does not allow them.
|
|
421
|
+
|
|
422
|
+
`run --remote --file input.txt ...` declares upload hashes before admission and
|
|
423
|
+
uploads bytes without forwarding the account key to storage. Failed uploads
|
|
424
|
+
request cancellation. Upload support must be advertised by the server.
|
|
425
|
+
Downloads verify authenticated size and SHA-256 metadata before writing files;
|
|
426
|
+
existing files and unsafe paths are refused. CLI/SDK downloads are bounded to
|
|
427
|
+
64 MiB; MCP inline artifacts and input files are limited to 1 MiB. Listing, creating and revoking API keys require fresh email OTP reauthentication; an existing
|
|
428
|
+
API key cannot grant new key authority. Checkout
|
|
429
|
+
commands return external links; payment confirmation remains in the browser.
|
|
430
|
+
|
|
431
|
+
The MCP server uses the same account, quote, run and artifact client. Agent
|
|
432
|
+
hosts must launch `skills-mcp --stdio`; the standalone default is loopback HTTP.
|
|
433
|
+
Configure its environment with the selected `HASNA_PROFILE` and isolated state
|
|
434
|
+
paths. `run_skill` accepts `remote:true`, `maxCredits`, `idempotency_key`, and
|
|
435
|
+
optional inline `files:[{name,base64,contentType}]`. An omitted ceiling permits
|
|
436
|
+
only free execution. `quote_skill` never submits a run.
|
|
437
|
+
|
|
438
|
+
```ts
|
|
439
|
+
import { RemoteSkillsAuthClient, createRemoteSkillsClient } from "@hasna/skills/sdk";
|
|
440
|
+
|
|
441
|
+
// Auth transports never write credentials; the embedding application owns storage.
|
|
442
|
+
const auth = new RemoteSkillsAuthClient("https://skills.example.com/api/v1");
|
|
443
|
+
await auth.requestCode("you@example.com");
|
|
444
|
+
// await auth.verifyCode("you@example.com", code);
|
|
445
|
+
|
|
446
|
+
// Uses the same selected profile and credential binding as CLI/MCP.
|
|
447
|
+
const client = await createRemoteSkillsClient(process.env);
|
|
448
|
+
if (!client) throw new Error("Configure an instance and sign in first");
|
|
449
|
+
const quote = await client.quoteRun("blog-article", {}, ["--topic", "Your topic"]);
|
|
450
|
+
// Obtain explicit user approval of quote.pricing.costCents before this call.
|
|
451
|
+
const run = await client.submitQuotedRun("blog-article", {}, ["--topic", "Your topic"], {
|
|
452
|
+
maxCredits: quote.pricing.costCents,
|
|
453
|
+
idempotencyKey: "article-001",
|
|
454
|
+
});
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
`submitRun` remains a low-level compatibility transport. New paid integrations
|
|
458
|
+
should use `submitQuotedRun` or `submitQuotedRunWithFiles` so capability and
|
|
459
|
+
approval checks run before submission. Credit counts are integers; `maxCostCents`
|
|
460
|
+
is a legacy spelling for the same credit ceiling. Missing billing capabilities
|
|
461
|
+
on an internal instance are explicit unsupported responses; this package does
|
|
462
|
+
not add a billing engine to the OSS server.
|
|
319
463
|
|
|
320
464
|
### Server database
|
|
321
465
|
|
|
@@ -324,11 +468,15 @@ different product: the schema, the organization scoping, and the run lifecycle a
|
|
|
324
468
|
identical either way.
|
|
325
469
|
|
|
326
470
|
```bash
|
|
327
|
-
skills-
|
|
328
|
-
HASNA_SKILLS_DATABASE_URL=<path>/server.db skills-
|
|
329
|
-
HASNA_SKILLS_DATABASE_URL=postgres://user:CHANGEME@host/skills skills-
|
|
471
|
+
skills-serve # SQLite at ~/.hasna/skills/server.db
|
|
472
|
+
HASNA_SKILLS_DATABASE_URL=<path>/server.db skills-serve
|
|
473
|
+
HASNA_SKILLS_DATABASE_URL=postgres://user:CHANGEME@host/skills skills-serve
|
|
330
474
|
```
|
|
331
475
|
|
|
476
|
+
> **Bin naming:** the canonical server bin is `skills-serve`; `skills-server` remains
|
|
477
|
+
> installed as a deprecated alias for one release (same entrypoint). `skills-worker`
|
|
478
|
+
> and `skills-migrate` are additional documented surfaces.
|
|
479
|
+
|
|
332
480
|
| `HASNA_SKILLS_DATABASE_URL` | Backend | Survives restart |
|
|
333
481
|
| --- | --- | --- |
|
|
334
482
|
| *(unset)* | SQLite at `<data dir>/server.db` | yes |
|
|
@@ -368,8 +516,8 @@ SQLite file, so it stays usable as a deploy gate.
|
|
|
368
516
|
|
|
369
517
|
`HASNA_SKILLS_DATABASE_URL` and `DATABASE_URL` are server-only. CLI, MCP, and SDK
|
|
370
518
|
clients never read them and never open a database connection: a client reaches
|
|
371
|
-
the cloud only through
|
|
372
|
-
|
|
519
|
+
the cloud only through the resolved API URL plus the resolved API key (see
|
|
520
|
+
[Credentials](#credentials)). The one exception is the repo-native storage
|
|
373
521
|
sync under [Storage Boundary](#storage-boundary), an operator tool that
|
|
374
522
|
intentionally reads the same variables.
|
|
375
523
|
|
|
@@ -387,7 +535,7 @@ Three things the server will not do:
|
|
|
387
535
|
against the same file — nothing more. A container without a persistent volume gets a
|
|
388
536
|
database in its own ephemeral layer, and two replicas each get their *own* database
|
|
389
537
|
rather than sharing one. Multi-replica and container deployments want Postgres; both
|
|
390
|
-
`skills-
|
|
538
|
+
`skills-serve` and `skills-worker` print the database they opened on startup, so a
|
|
391
539
|
split-brain SQLite setup shows up as two different paths in the logs.
|
|
392
540
|
|
|
393
541
|
<a id="storage-boundary"></a>
|
|
@@ -452,7 +600,7 @@ skills/ # Public skill contracts and local OSS skills
|
|
|
452
600
|
|---|---|---|
|
|
453
601
|
| Catalog skills | 86 | `SKILLS.length` (`src/lib/registry-data/`) |
|
|
454
602
|
| Categories | 17 | `CATEGORIES` (`src/lib/registry-types.ts`) |
|
|
455
|
-
| MCP tools |
|
|
603
|
+
| MCP tools | 56 | `tools/list` against a live `buildServer()` |
|
|
456
604
|
|
|
457
605
|
Every number in this table is re-derived from the source tree on each test run by
|
|
458
606
|
`src/lib/readme-derived-counts.test.ts`, so a drifted figure fails a test rather
|