CLI for the support platform. Agent-friendly with non-interactive defaults.
npm install @skillrecordings/cliCLI for the support platform. Agent-friendly with non-interactive defaults.
``bash
bunx @skillrecordings/cli
All commands support
--json for machine-readable output and reliable exit
codes.Adaptive Hints
The CLI prints adaptive onboarding/discovery hints to
stderr for new users.
Hints learn from usage and fade as you run more commands.Opt out:
- Use
--quiet
- Use --json
- Pipe output (non-TTY)Commands
$3
Initialize a new app integration with webhook secret.
`bash
Interactive (terminal only)
skill initNon-interactive (required for agents/scripts)
skill init my-appJSON output
skill init my-app --json
`Options:
-
--json - Output result as JSON (machine-readable)Exit codes:
-
0 - Success
- 1 - Error (name required in non-interactive mode, etc.)$3
Test integration endpoint health.
`bash
Using database lookup (recommended)
skill health total-typescriptDirect URL mode
skill health https://example.com --secret whsec_xxxList registered apps
skill health --listJSON output (for agents)
skill health total-typescript --json
`Options:
-
-s, --secret - Webhook secret (required for direct URL mode)
- -l, --list - List all registered apps
- --json - Output result as JSON (machine-readable)Exit codes:
-
0 - Health check passed
- 1 - Health check failed or errorJSON output structure:
`json
{
"success": true,
"endpoint": "https://...",
"status": "ok",
"responseTime": 730,
"actions": [
{ "name": "lookupUser", "status": "ok" },
{ "name": "getPurchases", "status": "ok" }
],
"summary": { "ok": 4, "notImplemented": 1, "errors": 0 }
}
`$3
Run evals against a dataset (e.g., routing classifier, canned response
matcher).
`bash
Run routing eval with defaults
skill eval routing path/to/dataset.jsonWith strict thresholds
skill eval routing dataset.json --min-precision 0.95 --min-recall 0.97JSON output for automation
skill eval routing dataset.json --jsonCustom thresholds
skill eval routing dataset.json \
--min-precision 0.92 \
--min-recall 0.95 \
--max-fp-rate 0.03 \
--max-fn-rate 0.02
`Arguments:
-
type - Eval type (e.g., routing)
- dataset - Path to JSON dataset fileOptions:
-
--json - Output result as JSON (machine-readable)
- --min-precision - Minimum precision threshold (default: 0.92)
- --min-recall - Minimum recall threshold (default: 0.95)
- --max-fp-rate - Maximum false positive rate (default: 0.03)
- --max-fn-rate - Maximum false negative rate (default: 0.02)Exit codes:
-
0 - All metrics passed thresholds
- 1 - One or more metrics below threshold or errorOutput includes:
- Precision, recall, false positive/negative rates
- Latency percentiles (p50, p95, p99)
- Token usage and estimated cost
- Category-level breakdown (if applicable)
App Onboarding Workflow
Typical flow for adding a new app integration:
`bash
1. Initialize with app name
skill init my-app --json
Returns: { "success": true, "appName": "my-app",
"webhookSecret": "whsec_xxx" }
2. Register webhook endpoint in your app
Save the webhook secret and configure your endpoint to:
POST /api/support-webhooks with Authorization: Bearer whsec_xxx
3. Test health before going live
skill health my-app
Verifies: endpoint reachable, signature verification works,
actions implemented
4. Run evals (optional, for routing/matching logic)
skill eval routing path/to/labeled-dataset.json --json5. Deploy and monitor
Check logs via Axiom/Langfuse for inbound messages
`All commands work non-interactively and report errors with exit codes
(0=success, 1=error).
Agent Usage
All commands support
--json for machine-readable output and
non-interactive operation:init command:
- Requires
name argument (non-interactive mode)
- Returns JSON: { "success": true, "appName": "...",
- Use --json for reliable parsinghealth command:
- Use
--json for JSON output (structured for parsing)
- Use --list to discover all registered apps
- Returns exit code 0 if healthy, 1 if any check failseval command:
- Requires
type and dataset arguments
- Accepts custom threshold gates (precision, recall, false
positive/negative rates)
- Returns exit code 0 if all metrics pass, 1 otherwise
- Use --json for machine-readable reportError handling:
- All commands output
{ "success": false, "error": "message" } on
JSON mode
- Check exit codes: 0 = success, 1 = error
- Never interactive in non-TTY environments (CI/CD safe)Secrets Management
The CLI uses a layered secrets system:
1. 1Password (preferred) - Service account token resolves secrets directly
2. Encrypted
.env.encrypted - Age-encrypted env file for offline/CI use
3. Plain .env.local - Local development fallback$3
`
1Password (OP_SERVICE_ACCOUNT_TOKEN set?)
↓ yes → resolve from 1Password vault
↓ no
.env.encrypted exists + AGE_SECRET_KEY available?
↓ yes → decrypt and load
↓ no
.env.local exists?
↓ yes → load plain env vars
↓ no → error: missing secrets
`$3
Step 1: Add to
secret-refs.ts`typescript
// packages/cli/src/core/secret-refs.ts
export const SECRET_REFS = {
// ... existing secrets
MY_NEW_KEY: 'op://Support/skill-cli/MY_NEW_KEY',
} as const
`Step 2: Add to 1Password
`bash
Using op CLI
op item edit "skill-cli" --vault "Support" "MY_NEW_KEY=your-secret-value"Or via 1Password UI:
1. Open Support vault → skill-cli item
2. Add new field: MY_NEW_KEY = your-value
`Step 3: Update
.env.encrypted`bash
Decrypt current secrets
AGE_KEY=$(op read "op://Support/skill-cli-age-key/password")
age -d -i <(echo "$AGE_KEY") .env.encrypted > .env.localAdd new secret to .env.local
echo "MY_NEW_KEY=your-secret-value" >> .env.localRe-encrypt
AGE_PUB=$(echo "$AGE_KEY" | age-keygen -y)
age -r "$AGE_PUB" .env.local > .env.encryptedVerify
age -d -i <(echo "$AGE_KEY") .env.encrypted | grep MY_NEW_KEY
`Step 4: Commit changes
`bash
git add packages/cli/src/core/secret-refs.ts packages/cli/.env.encrypted
git commit -m "chore(cli): add MY_NEW_KEY secret"
`$3
`bash
1. Update in 1Password
op item edit "skill-cli" --vault "Support" "MY_KEY=new-value"2. Update .env.encrypted (same process as adding)
AGE_KEY=$(op read "op://Support/skill-cli-age-key/password")
age -d -i <(echo "$AGE_KEY") .env.encrypted > .env.localEdit .env.local with new value
sed -i '' 's/MY_KEY=.*/MY_KEY=new-value/' .env.localRe-encrypt
AGE_PUB=$(echo "$AGE_KEY" | age-keygen -y)
age -r "$AGE_PUB" .env.local > .env.encrypted
`$3
`bash
Check current auth status
skill auth statusValidate 1Password token
skill auth loginShow service account info
skill auth whoamiInteractive setup wizard
skill auth setup
`$3
| Item | Location |
|------|----------|
| Secrets |
op://Support/skill-cli/* |
| Age keypair | op://Support/skill-cli-age-key/password |
| Encrypted env | packages/cli/.env.encrypted |
| Secret refs | packages/cli/src/core/secret-refs.ts |$3
For CI environments without 1Password:
`bash
Set age key as CI secret, then:
echo "$AGE_SECRET_KEY" > /tmp/age.key
age -d -i /tmp/age.key .env.encrypted > .env.local
rm /tmp/age.key
`Or use 1Password service account:
`bash
export OP_SERVICE_ACCOUNT_TOKEN="$OP_TOKEN"
skill auth status # Verifies connection
skill front inbox # Commands auto-resolve secrets
`Implementation
-
packages/cli/src/commands/ - Command implementations
- packages/cli/src/index.ts - CLI entry point
- Entry point: #!/usr/bin/env bun (runs with Bun directly)Do / Don't
- Do use
--json flag for automation/agents/scripts
- Do check exit codes in shell scripts
- Do pass name argument to init in CI/CD (non-interactive required)
- Don't rely on interactive prompts outside terminal
- Don't parse stdout (use --json` for structured output)