npm package: @skillrecordings/cli
Description: Agent-friendly CLI for the Skill Recordings support platform.
Latest version: 0.21.0

# @skillrecordings/cli

Agent-friendly CLI for the Skill Recordings support platform.

## Setup (2 minutes)

You need: a GitHub account in the `skillrecordings` org.

```bash
# 1. Install (private repo, so use gh)
gh auth login
gh api -H "Accept: application/vnd.github.raw" \
  repos/skillrecordings/support/contents/packages/cli/install.sh?ref=main | bash

# 2. Add to PATH (if not already)
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc

# 3. Authenticate (opens browser, no other tools needed)
skill auth setup

# 4. Verify everything works
skill doctor
```

That's it. No 1Password CLI, no age keys, no manual secret management.

The CLI authenticates via GitHub device flow → the broker verifies your org
membership → secrets are delivered encrypted and held in memory only.

## Install troubleshooting

| Symptom | Fix |
|---|---|
| `gh: command not found` | Install GitHub CLI: https://cli.github.com/ |
| `gh` asks you to log in | Run `gh auth login`, then `gh auth status` |
| `HTTP 404` / repo access failure on bootstrap | Confirm you can access the private repo: `gh release list --repo skillrecordings/support --limit 5` |
| `skill: command not found` after install | Add `~/.local/bin` to PATH |

Quick verification:

```bash
gh auth status
which skill
skill --version
```

## Commands

```bash
skill <command> [options]
```

All commands support `--json` for machine-readable output.

| Command | What it does |
|---|---|
| `skill auth setup` | One-command bootstrap (GitHub device flow) |
| `skill auth status` | Session + provider status |
| `skill doctor` | Deep health check with remediation hints |
| `skill health <app>` | Test app webhook endpoint |
| `skill health --list` | List registered apps |
| `skill init <name>` | Initialize new app integration |
| `skill eval routing <dataset>` | Run routing classifier evals |
| `skill auth oauth-spike` | Inspect broker readiness |

## How Auth Works

```
skill auth setup
    → GitHub device flow (approve in browser)
    → Broker verifies skillrecordings org membership
    → Short-lived session tokens issued (15min access / 8hr refresh)
    → skill auth exec decrypts secrets in memory per-command
```

**Broker endpoints** (on `skill-support-agent-front.vercel.app`):

| Endpoint | Purpose |
|---|---|
| `POST /api/auth/device/start` | Start GitHub device flow |
| `POST /api/auth/device/poll` | Exchange device code for session |
| `POST /api/auth/session/refresh` | Refresh session, re-check membership |
| `POST /api/env/materialize` | Age-encrypted env delivery |

**Legacy path:** 1Password CLI + `skill auth setup --legacy` still works as
admin/break-glass mode.

## App Onboarding

```bash
# 1. Initialize
skill init my-app --json

# 2. Register webhook in your app (use returned secret)
# POST /api/support-webhooks with Authorization: Bearer whsec_xxx

# 3. Verify
skill health my-app

# 4. Run evals (optional)
skill eval routing labeled-dataset.json --json
```

## Health Check

```bash
# Quick check
skill health total-typescript

# All apps
skill health --list

# Deep system check
skill doctor --json
```

## Agent Usage

- `--json` on every command for structured output
- `--quiet` suppresses adaptive hints
- Exit codes: `0` = success, `1` = error
- Non-interactive in non-TTY environments (CI/CD safe)
- Error shape: `{ "success": false, "error": "message" }`

## Secrets Management

The broker handles secrets for most users. Admins who need direct access:

### Resolution Order

```
OAuth Broker (default, v0.19.0+)
    → GitHub auth → broker decrypts → ephemeral age envelope → memory only
1Password (admin/break-glass)
    → OP_SERVICE_ACCOUNT_TOKEN → resolve from vault
.env.encrypted (CI fallback)
    → SKILL_AGE_KEY → decrypt and load
.env.local (local dev fallback)
    → load plain env vars
```

### Adding a Secret

1. Add ref to `packages/cli/src/core/secret-refs.ts`
2. Add value to 1Password: `op item edit "skill-cli" --vault "Support" "MY_KEY=value"`
3. Update `.env.encrypted` (see below)
4. Commit: `git add secret-refs.ts .env.encrypted`

### Updating `.env.encrypted`

```bash
AGE_KEY=$(op read "op://Support/skill-cli-age-key/private_key")
age -d -i <(echo "$AGE_KEY") .env.encrypted > .env.local
# edit .env.local
AGE_PUB=$(echo "$AGE_KEY" | age-keygen -y)
age -r "$AGE_PUB" .env.local > .env.encrypted
rm .env.local
```

### Key Locations

| Item | Location |
|---|---|
| Secrets | `op://Support/skill-cli/*` |
| Age keypair | `op://Support/skill-cli-age-key/private_key` |
| Encrypted env | `packages/cli/.env.encrypted` |
| Secret refs | `packages/cli/src/core/secret-refs.ts` |

### CI/CD

```bash
# With 1Password service account
export OP_SERVICE_ACCOUNT_TOKEN="$OP_TOKEN"
skill auth status

# Or with age key
echo "$SKILL_AGE_KEY" > /tmp/age.key
age -d -i /tmp/age.key .env.encrypted > .env.local
rm /tmp/age.key
```

## Adaptive Hints

New users see contextual onboarding hints on `stderr`. They fade with usage.
Suppress with `--quiet`, `--json`, or piped output.

## Implementation

- `packages/cli/src/commands/` — command implementations
- `packages/cli/src/index.ts` — entry point (`#!/usr/bin/env bun`)