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