@hasna/skills 0.2.0 → 0.3.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 +100 -36
- package/bin/index.js +2151 -650
- package/bin/mcp.js +1787 -625
- package/bin/migrate.js +5 -0
- package/bin/server.js +365 -198
- package/bin/worker.js +346 -179
- package/dist/cli/cli.test-utils.d.ts +14 -0
- package/dist/cli/commands/publish.d.ts +14 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1100 -152
- 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 +246 -0
- package/dist/lib/portable-skills-files.d.ts +9 -0
- package/dist/lib/portable-skills.d.ts +2 -2
- package/dist/lib/remote-client.d.ts +20 -10
- package/dist/lib/remote-registry.d.ts +31 -11
- package/dist/lib/run-routing.d.ts +6 -4
- package/dist/lib/vendor-host-policy.d.ts +31 -0
- package/dist/sdk/index.d.ts +6 -0
- package/dist/sdk/index.js +1738 -572
- package/dist/server/artifact-storage.d.ts +11 -0
- package/dist/server/skills-api.d.ts +13 -2
- package/dist/storage.js +9 -14
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -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 |
|
|
@@ -122,7 +180,7 @@ requirements explicitly document local provider use.
|
|
|
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`,
|
|
@@ -307,8 +367,8 @@ skills mcp --register all # Register with all supported agents
|
|
|
307
367
|
## Skills API
|
|
308
368
|
|
|
309
369
|
```bash
|
|
310
|
-
skills setup --api-url https://skills.example.com
|
|
311
|
-
skills auth login --api-key "$
|
|
370
|
+
skills setup --api-url https://skills.example.com # only for your own instance
|
|
371
|
+
skills auth login --api-key "$HASNA_SKILLS_API_KEY"
|
|
312
372
|
skills billing status
|
|
313
373
|
```
|
|
314
374
|
|
|
@@ -324,11 +384,15 @@ different product: the schema, the organization scoping, and the run lifecycle a
|
|
|
324
384
|
identical either way.
|
|
325
385
|
|
|
326
386
|
```bash
|
|
327
|
-
skills-
|
|
328
|
-
HASNA_SKILLS_DATABASE_URL=<path>/server.db skills-
|
|
329
|
-
HASNA_SKILLS_DATABASE_URL=postgres://user:CHANGEME@host/skills skills-
|
|
387
|
+
skills-serve # SQLite at ~/.hasna/skills/server.db
|
|
388
|
+
HASNA_SKILLS_DATABASE_URL=<path>/server.db skills-serve
|
|
389
|
+
HASNA_SKILLS_DATABASE_URL=postgres://user:CHANGEME@host/skills skills-serve
|
|
330
390
|
```
|
|
331
391
|
|
|
392
|
+
> **Bin naming:** the canonical server bin is `skills-serve`; `skills-server` remains
|
|
393
|
+
> installed as a deprecated alias for one release (same entrypoint). `skills-worker`
|
|
394
|
+
> and `skills-migrate` are additional documented surfaces.
|
|
395
|
+
|
|
332
396
|
| `HASNA_SKILLS_DATABASE_URL` | Backend | Survives restart |
|
|
333
397
|
| --- | --- | --- |
|
|
334
398
|
| *(unset)* | SQLite at `<data dir>/server.db` | yes |
|
|
@@ -368,8 +432,8 @@ SQLite file, so it stays usable as a deploy gate.
|
|
|
368
432
|
|
|
369
433
|
`HASNA_SKILLS_DATABASE_URL` and `DATABASE_URL` are server-only. CLI, MCP, and SDK
|
|
370
434
|
clients never read them and never open a database connection: a client reaches
|
|
371
|
-
the cloud only through
|
|
372
|
-
|
|
435
|
+
the cloud only through the resolved API URL plus the resolved API key (see
|
|
436
|
+
[Credentials](#credentials)). The one exception is the repo-native storage
|
|
373
437
|
sync under [Storage Boundary](#storage-boundary), an operator tool that
|
|
374
438
|
intentionally reads the same variables.
|
|
375
439
|
|
|
@@ -387,7 +451,7 @@ Three things the server will not do:
|
|
|
387
451
|
against the same file — nothing more. A container without a persistent volume gets a
|
|
388
452
|
database in its own ephemeral layer, and two replicas each get their *own* database
|
|
389
453
|
rather than sharing one. Multi-replica and container deployments want Postgres; both
|
|
390
|
-
`skills-
|
|
454
|
+
`skills-serve` and `skills-worker` print the database they opened on startup, so a
|
|
391
455
|
split-brain SQLite setup shows up as two different paths in the logs.
|
|
392
456
|
|
|
393
457
|
<a id="storage-boundary"></a>
|