@skillrecordings/cli 0.18.2 → 0.20.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 +89 -293
- package/dist/index.js +2057 -1059
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,375 +1,171 @@
|
|
|
1
1
|
# @skillrecordings/cli
|
|
2
2
|
|
|
3
|
-
CLI for the support platform.
|
|
3
|
+
Agent-friendly CLI for the Skill Recordings support platform.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Setup (2 minutes)
|
|
6
|
+
|
|
7
|
+
You need: a GitHub account in the `skillrecordings` org.
|
|
6
8
|
|
|
7
9
|
```bash
|
|
10
|
+
# 1. Install
|
|
8
11
|
curl -fsSL https://raw.githubusercontent.com/skillrecordings/support/main/packages/cli/install.sh | bash
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
Installs to `~/.local/bin/skill`. Add to your PATH if needed:
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
# 2. Add to PATH (if not already)
|
|
14
14
|
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
After install, run `skill auth setup` to configure credentials.
|
|
18
|
-
|
|
19
|
-
## Usage
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
bunx @skillrecordings/cli <command> [options]
|
|
23
|
-
|
|
24
|
-
# or with direct import
|
|
25
|
-
skill <command> [options]
|
|
26
|
-
```
|
|
27
15
|
|
|
28
|
-
|
|
29
|
-
codes.
|
|
30
|
-
|
|
31
|
-
## 1Password Quickstart (60 seconds)
|
|
32
|
-
|
|
33
|
-
If you already have access to the Support vault:
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
# 1) Install required CLI
|
|
37
|
-
brew install 1password-cli
|
|
38
|
-
|
|
39
|
-
# 2) Optional but recommended: cache OP token in local secrets CLI
|
|
40
|
-
secrets add skill_support_1password_service_account_token
|
|
41
|
-
|
|
42
|
-
# 3) Run one setup command
|
|
16
|
+
# 3. Authenticate (opens browser, no other tools needed)
|
|
43
17
|
skill auth setup
|
|
44
18
|
|
|
45
|
-
# 4
|
|
19
|
+
# 4. Verify everything works
|
|
46
20
|
skill doctor
|
|
47
21
|
```
|
|
48
22
|
|
|
49
|
-
|
|
50
|
-
- `secrets` CLI is optional. If missing, `skill auth setup` falls back to `op signin`.
|
|
51
|
-
- Setup writes `SKILL_AGE_KEY` to `~/.config/skill/age.key` so `.env.encrypted` works without keychain.
|
|
23
|
+
That's it. No 1Password CLI, no age keys, no manual secret management.
|
|
52
24
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
The CLI prints adaptive onboarding/discovery hints to `stderr` for new users.
|
|
56
|
-
Hints learn from usage and fade as you run more commands.
|
|
57
|
-
|
|
58
|
-
**Opt out:**
|
|
59
|
-
- Use `--quiet`
|
|
60
|
-
- Use `--json`
|
|
61
|
-
- Pipe output (non-TTY)
|
|
25
|
+
The CLI authenticates via GitHub device flow → the broker verifies your org
|
|
26
|
+
membership → secrets are delivered encrypted and held in memory only.
|
|
62
27
|
|
|
63
28
|
## Commands
|
|
64
29
|
|
|
65
|
-
### `skill init <name>`
|
|
66
|
-
|
|
67
|
-
Initialize a new app integration with webhook secret.
|
|
68
|
-
|
|
69
30
|
```bash
|
|
70
|
-
|
|
71
|
-
skill init
|
|
72
|
-
|
|
73
|
-
# Non-interactive (required for agents/scripts)
|
|
74
|
-
skill init my-app
|
|
75
|
-
|
|
76
|
-
# JSON output
|
|
77
|
-
skill init my-app --json
|
|
31
|
+
skill <command> [options]
|
|
78
32
|
```
|
|
79
33
|
|
|
80
|
-
|
|
81
|
-
- `--json` - Output result as JSON (machine-readable)
|
|
82
|
-
|
|
83
|
-
**Exit codes:**
|
|
84
|
-
- `0` - Success
|
|
85
|
-
- `1` - Error (name required in non-interactive mode, etc.)
|
|
86
|
-
|
|
87
|
-
### `skill health <slug|url>`
|
|
88
|
-
|
|
89
|
-
Test integration endpoint health.
|
|
34
|
+
All commands support `--json` for machine-readable output.
|
|
90
35
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
skill
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
skill health
|
|
36
|
+
| Command | What it does |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `skill auth setup` | One-command bootstrap (GitHub device flow) |
|
|
39
|
+
| `skill auth status` | Session + provider status |
|
|
40
|
+
| `skill doctor` | Deep health check with remediation hints |
|
|
41
|
+
| `skill health <app>` | Test app webhook endpoint |
|
|
42
|
+
| `skill health --list` | List registered apps |
|
|
43
|
+
| `skill init <name>` | Initialize new app integration |
|
|
44
|
+
| `skill eval routing <dataset>` | Run routing classifier evals |
|
|
45
|
+
| `skill auth oauth-spike` | Inspect broker readiness |
|
|
97
46
|
|
|
98
|
-
|
|
99
|
-
skill health --list
|
|
100
|
-
|
|
101
|
-
# JSON output (for agents)
|
|
102
|
-
skill health total-typescript --json
|
|
103
|
-
```
|
|
47
|
+
## How Auth Works
|
|
104
48
|
|
|
105
|
-
**Options:**
|
|
106
|
-
- `-s, --secret <secret>` - Webhook secret (required for direct URL mode)
|
|
107
|
-
- `-l, --list` - List all registered apps
|
|
108
|
-
- `--json` - Output result as JSON (machine-readable)
|
|
109
|
-
|
|
110
|
-
**Exit codes:**
|
|
111
|
-
- `0` - Health check passed
|
|
112
|
-
- `1` - Health check failed or error
|
|
113
|
-
|
|
114
|
-
**JSON output structure:**
|
|
115
|
-
```json
|
|
116
|
-
{
|
|
117
|
-
"success": true,
|
|
118
|
-
"endpoint": "https://...",
|
|
119
|
-
"status": "ok",
|
|
120
|
-
"responseTime": 730,
|
|
121
|
-
"actions": [
|
|
122
|
-
{ "name": "lookupUser", "status": "ok" },
|
|
123
|
-
{ "name": "getPurchases", "status": "ok" }
|
|
124
|
-
],
|
|
125
|
-
"summary": { "ok": 4, "notImplemented": 1, "errors": 0 }
|
|
126
|
-
}
|
|
127
49
|
```
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
```bash
|
|
135
|
-
# Run routing eval with defaults
|
|
136
|
-
skill eval routing path/to/dataset.json
|
|
137
|
-
|
|
138
|
-
# With strict thresholds
|
|
139
|
-
skill eval routing dataset.json --min-precision 0.95 --min-recall 0.97
|
|
140
|
-
|
|
141
|
-
# JSON output for automation
|
|
142
|
-
skill eval routing dataset.json --json
|
|
143
|
-
|
|
144
|
-
# Custom thresholds
|
|
145
|
-
skill eval routing dataset.json \
|
|
146
|
-
--min-precision 0.92 \
|
|
147
|
-
--min-recall 0.95 \
|
|
148
|
-
--max-fp-rate 0.03 \
|
|
149
|
-
--max-fn-rate 0.02
|
|
50
|
+
skill auth setup
|
|
51
|
+
→ GitHub device flow (approve in browser)
|
|
52
|
+
→ Broker verifies skillrecordings org membership
|
|
53
|
+
→ Short-lived session tokens issued (15min access / 8hr refresh)
|
|
54
|
+
→ skill auth exec decrypts secrets in memory per-command
|
|
150
55
|
```
|
|
151
56
|
|
|
152
|
-
**
|
|
153
|
-
- `type` - Eval type (e.g., `routing`)
|
|
154
|
-
- `dataset` - Path to JSON dataset file
|
|
155
|
-
|
|
156
|
-
**Options:**
|
|
157
|
-
- `--json` - Output result as JSON (machine-readable)
|
|
158
|
-
- `--min-precision <number>` - Minimum precision threshold (default: 0.92)
|
|
159
|
-
- `--min-recall <number>` - Minimum recall threshold (default: 0.95)
|
|
160
|
-
- `--max-fp-rate <number>` - Maximum false positive rate (default: 0.03)
|
|
161
|
-
- `--max-fn-rate <number>` - Maximum false negative rate (default: 0.02)
|
|
57
|
+
**Broker endpoints** (on `skill-support-agent-front.vercel.app`):
|
|
162
58
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
59
|
+
| Endpoint | Purpose |
|
|
60
|
+
|---|---|
|
|
61
|
+
| `POST /api/auth/device/start` | Start GitHub device flow |
|
|
62
|
+
| `POST /api/auth/device/poll` | Exchange device code for session |
|
|
63
|
+
| `POST /api/auth/session/refresh` | Refresh session, re-check membership |
|
|
64
|
+
| `POST /api/env/materialize` | Age-encrypted env delivery |
|
|
166
65
|
|
|
167
|
-
**
|
|
168
|
-
-
|
|
169
|
-
- Latency percentiles (p50, p95, p99)
|
|
170
|
-
- Token usage and estimated cost
|
|
171
|
-
- Category-level breakdown (if applicable)
|
|
66
|
+
**Legacy path:** 1Password CLI + `skill auth setup --legacy` still works as
|
|
67
|
+
admin/break-glass mode.
|
|
172
68
|
|
|
173
|
-
## App Onboarding
|
|
174
|
-
|
|
175
|
-
Typical flow for adding a new app integration:
|
|
69
|
+
## App Onboarding
|
|
176
70
|
|
|
177
71
|
```bash
|
|
178
|
-
# 1. Initialize
|
|
72
|
+
# 1. Initialize
|
|
179
73
|
skill init my-app --json
|
|
180
|
-
# Returns: { "success": true, "appName": "my-app",
|
|
181
|
-
# "webhookSecret": "whsec_xxx" }
|
|
182
74
|
|
|
183
|
-
# 2. Register webhook
|
|
184
|
-
# Save the webhook secret and configure your endpoint to:
|
|
75
|
+
# 2. Register webhook in your app (use returned secret)
|
|
185
76
|
# POST /api/support-webhooks with Authorization: Bearer whsec_xxx
|
|
186
77
|
|
|
187
|
-
# 3.
|
|
78
|
+
# 3. Verify
|
|
188
79
|
skill health my-app
|
|
189
|
-
# Verifies: endpoint reachable, signature verification works,
|
|
190
|
-
# actions implemented
|
|
191
|
-
|
|
192
|
-
# 4. Run evals (optional, for routing/matching logic)
|
|
193
|
-
skill eval routing path/to/labeled-dataset.json --json
|
|
194
80
|
|
|
195
|
-
#
|
|
196
|
-
|
|
81
|
+
# 4. Run evals (optional)
|
|
82
|
+
skill eval routing labeled-dataset.json --json
|
|
197
83
|
```
|
|
198
84
|
|
|
199
|
-
|
|
200
|
-
(0=success, 1=error).
|
|
85
|
+
## Health Check
|
|
201
86
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
non-interactive operation:
|
|
206
|
-
|
|
207
|
-
**init command:**
|
|
208
|
-
- Requires `name` argument (non-interactive mode)
|
|
209
|
-
- Returns JSON: `{ "success": true, "appName": "...",
|
|
210
|
-
"webhookSecret": "whsec_..." }`
|
|
211
|
-
- Use `--json` for reliable parsing
|
|
212
|
-
|
|
213
|
-
**health command:**
|
|
214
|
-
- Use `--json` for JSON output (structured for parsing)
|
|
215
|
-
- Use `--list` to discover all registered apps
|
|
216
|
-
- Returns exit code 0 if healthy, 1 if any check fails
|
|
217
|
-
|
|
218
|
-
**eval command:**
|
|
219
|
-
- Requires `type` and `dataset` arguments
|
|
220
|
-
- Accepts custom threshold gates (precision, recall, false
|
|
221
|
-
positive/negative rates)
|
|
222
|
-
- Returns exit code 0 if all metrics pass, 1 otherwise
|
|
223
|
-
- Use `--json` for machine-readable report
|
|
224
|
-
|
|
225
|
-
**Error handling:**
|
|
226
|
-
- All commands output `{ "success": false, "error": "message" }` on
|
|
227
|
-
JSON mode
|
|
228
|
-
- Check exit codes: 0 = success, 1 = error
|
|
229
|
-
- Never interactive in non-TTY environments (CI/CD safe)
|
|
230
|
-
|
|
231
|
-
## Secrets Management
|
|
232
|
-
|
|
233
|
-
The CLI uses a layered secrets system:
|
|
234
|
-
|
|
235
|
-
1. **1Password (preferred)** - Service account token resolves secrets directly
|
|
236
|
-
2. **Encrypted `.env.encrypted`** - Age-encrypted env file for offline/CI use
|
|
237
|
-
3. **Plain `.env.local`** - Local development fallback
|
|
87
|
+
```bash
|
|
88
|
+
# Quick check
|
|
89
|
+
skill health total-typescript
|
|
238
90
|
|
|
239
|
-
|
|
91
|
+
# All apps
|
|
92
|
+
skill health --list
|
|
240
93
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
↓ yes → resolve from 1Password vault
|
|
244
|
-
↓ no
|
|
245
|
-
.env.encrypted exists + SKILL_AGE_KEY available?
|
|
246
|
-
↓ yes → decrypt and load
|
|
247
|
-
↓ no
|
|
248
|
-
.env.local exists?
|
|
249
|
-
↓ yes → load plain env vars
|
|
250
|
-
↓ no → error: missing secrets
|
|
94
|
+
# Deep system check
|
|
95
|
+
skill doctor --json
|
|
251
96
|
```
|
|
252
97
|
|
|
253
|
-
|
|
98
|
+
## Agent Usage
|
|
254
99
|
|
|
255
|
-
|
|
100
|
+
- `--json` on every command for structured output
|
|
101
|
+
- `--quiet` suppresses adaptive hints
|
|
102
|
+
- Exit codes: `0` = success, `1` = error
|
|
103
|
+
- Non-interactive in non-TTY environments (CI/CD safe)
|
|
104
|
+
- Error shape: `{ "success": false, "error": "message" }`
|
|
256
105
|
|
|
257
|
-
|
|
258
|
-
// packages/cli/src/core/secret-refs.ts
|
|
259
|
-
export const SECRET_REFS = {
|
|
260
|
-
// ... existing secrets
|
|
261
|
-
MY_NEW_KEY: 'op://Support/skill-cli/MY_NEW_KEY',
|
|
262
|
-
} as const
|
|
263
|
-
```
|
|
106
|
+
## Secrets Management
|
|
264
107
|
|
|
265
|
-
|
|
108
|
+
The broker handles secrets for most users. Admins who need direct access:
|
|
266
109
|
|
|
267
|
-
|
|
268
|
-
# Using op CLI
|
|
269
|
-
op item edit "skill-cli" --vault "Support" "MY_NEW_KEY=your-secret-value"
|
|
110
|
+
### Resolution Order
|
|
270
111
|
|
|
271
|
-
# Or via 1Password UI:
|
|
272
|
-
# 1. Open Support vault → skill-cli item
|
|
273
|
-
# 2. Add new field: MY_NEW_KEY = your-value
|
|
274
112
|
```
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
# Add new secret to .env.local
|
|
284
|
-
echo "MY_NEW_KEY=your-secret-value" >> .env.local
|
|
285
|
-
|
|
286
|
-
# Re-encrypt
|
|
287
|
-
AGE_PUB=$(echo "$AGE_KEY" | age-keygen -y)
|
|
288
|
-
age -r "$AGE_PUB" .env.local > .env.encrypted
|
|
289
|
-
|
|
290
|
-
# Verify
|
|
291
|
-
age -d -i <(echo "$AGE_KEY") .env.encrypted | grep MY_NEW_KEY
|
|
113
|
+
OAuth Broker (default, v0.19.0+)
|
|
114
|
+
→ GitHub auth → broker decrypts → ephemeral age envelope → memory only
|
|
115
|
+
1Password (admin/break-glass)
|
|
116
|
+
→ OP_SERVICE_ACCOUNT_TOKEN → resolve from vault
|
|
117
|
+
.env.encrypted (CI fallback)
|
|
118
|
+
→ SKILL_AGE_KEY → decrypt and load
|
|
119
|
+
.env.local (local dev fallback)
|
|
120
|
+
→ load plain env vars
|
|
292
121
|
```
|
|
293
122
|
|
|
294
|
-
|
|
123
|
+
### Adding a Secret
|
|
295
124
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
125
|
+
1. Add ref to `packages/cli/src/core/secret-refs.ts`
|
|
126
|
+
2. Add value to 1Password: `op item edit "skill-cli" --vault "Support" "MY_KEY=value"`
|
|
127
|
+
3. Update `.env.encrypted` (see below)
|
|
128
|
+
4. Commit: `git add secret-refs.ts .env.encrypted`
|
|
300
129
|
|
|
301
|
-
### Updating
|
|
130
|
+
### Updating `.env.encrypted`
|
|
302
131
|
|
|
303
132
|
```bash
|
|
304
|
-
# 1. Update in 1Password
|
|
305
|
-
op item edit "skill-cli" --vault "Support" "MY_KEY=new-value"
|
|
306
|
-
|
|
307
|
-
# 2. Update .env.encrypted (same process as adding)
|
|
308
133
|
AGE_KEY=$(op read "op://Support/skill-cli-age-key/private_key")
|
|
309
134
|
age -d -i <(echo "$AGE_KEY") .env.encrypted > .env.local
|
|
310
|
-
|
|
311
|
-
# Edit .env.local with new value
|
|
312
|
-
sed -i '' 's/MY_KEY=.*/MY_KEY=new-value/' .env.local
|
|
313
|
-
|
|
314
|
-
# Re-encrypt
|
|
135
|
+
# edit .env.local
|
|
315
136
|
AGE_PUB=$(echo "$AGE_KEY" | age-keygen -y)
|
|
316
137
|
age -r "$AGE_PUB" .env.local > .env.encrypted
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
### Auth Commands
|
|
320
|
-
|
|
321
|
-
```bash
|
|
322
|
-
# Check current auth status
|
|
323
|
-
skill auth status
|
|
324
|
-
|
|
325
|
-
# Validate 1Password token
|
|
326
|
-
skill auth login
|
|
327
|
-
|
|
328
|
-
# Show service account info
|
|
329
|
-
skill auth whoami
|
|
330
|
-
|
|
331
|
-
# Interactive setup wizard
|
|
332
|
-
skill auth setup
|
|
138
|
+
rm .env.local
|
|
333
139
|
```
|
|
334
140
|
|
|
335
141
|
### Key Locations
|
|
336
142
|
|
|
337
143
|
| Item | Location |
|
|
338
|
-
|
|
144
|
+
|---|---|
|
|
339
145
|
| Secrets | `op://Support/skill-cli/*` |
|
|
340
146
|
| Age keypair | `op://Support/skill-cli-age-key/private_key` |
|
|
341
147
|
| Encrypted env | `packages/cli/.env.encrypted` |
|
|
342
148
|
| Secret refs | `packages/cli/src/core/secret-refs.ts` |
|
|
343
149
|
|
|
344
|
-
### CI/CD
|
|
345
|
-
|
|
346
|
-
For CI environments without 1Password:
|
|
150
|
+
### CI/CD
|
|
347
151
|
|
|
348
152
|
```bash
|
|
349
|
-
#
|
|
153
|
+
# With 1Password service account
|
|
154
|
+
export OP_SERVICE_ACCOUNT_TOKEN="$OP_TOKEN"
|
|
155
|
+
skill auth status
|
|
156
|
+
|
|
157
|
+
# Or with age key
|
|
350
158
|
echo "$SKILL_AGE_KEY" > /tmp/age.key
|
|
351
159
|
age -d -i /tmp/age.key .env.encrypted > .env.local
|
|
352
160
|
rm /tmp/age.key
|
|
353
161
|
```
|
|
354
162
|
|
|
355
|
-
|
|
163
|
+
## Adaptive Hints
|
|
356
164
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
skill auth status # Verifies connection
|
|
360
|
-
skill front inbox # Commands auto-resolve secrets
|
|
361
|
-
```
|
|
165
|
+
New users see contextual onboarding hints on `stderr`. They fade with usage.
|
|
166
|
+
Suppress with `--quiet`, `--json`, or piped output.
|
|
362
167
|
|
|
363
168
|
## Implementation
|
|
364
169
|
|
|
365
|
-
- `packages/cli/src/commands/`
|
|
366
|
-
- `packages/cli/src/index.ts`
|
|
367
|
-
- Entry point: `#!/usr/bin/env bun` (runs with Bun directly)
|
|
368
|
-
|
|
369
|
-
## Do / Don't
|
|
370
|
-
|
|
371
|
-
- Do use `--json` flag for automation/agents/scripts
|
|
372
|
-
- Do check exit codes in shell scripts
|
|
373
|
-
- Do pass `name` argument to `init` in CI/CD (non-interactive required)
|
|
374
|
-
- Don't rely on interactive prompts outside terminal
|
|
375
|
-
- Don't parse stdout (use `--json` for structured output)
|
|
170
|
+
- `packages/cli/src/commands/` — command implementations
|
|
171
|
+
- `packages/cli/src/index.ts` — entry point (`#!/usr/bin/env bun`)
|