CLI for the SavvyCal Appointments API.
pnpm install
pnpm buildAfter building, the savvycal binary is available at ./dist/index.js.
# Authenticate with an API token (JWT or sk_* key)
savvycal auth login --token <token>
# Authenticate with a demo key
savvycal auth login --demo <key>savvycal auth status # Show current auth state
savvycal auth logout # Clear stored credentials| Variable | Description |
|---|---|
SAVVYCAL_API_TOKEN |
API token (JWT or demo key) |
SAVVYCAL_ACCOUNT |
Account ID |
SAVVYCAL_BASE_URL |
API base URL (default: https://api.savvycal.app) |
Tokens, account, and base URL resolve in this order (highest priority first):
- CLI flag (
--token,--account,--base-url) - Environment variable
- Config file (
~/.config/savvycal/config.json)
savvycal services list
savvycal services get <id>
savvycal services create --name "My Service" --duration 30
savvycal services update <id> --name "Updated Name"
savvycal services delete <id>savvycal appointments cancel <id>
savvycal appointments confirm <id>
savvycal appointments reschedule <id> --start-at "2026-04-01T10:00:00Z"
savvycal providers deactivate <id>Parent IDs are passed as options:
savvycal provider-schedules create --provider-id <provider-id> --time-zone "America/Denver"
savvycal provider-schedules list --provider-id <provider-id>Public endpoints live under the public namespace:
savvycal public service-slots list --service-id <id> --limit 5
savvycal public service-earliest-slot get --service-id <id>
savvycal public appointments create --data '{"service_id": "...", "start_at": "..."}'
savvycal public booking-intents create --data '{"service_id": "..."}'Write commands accept body data in three ways:
# Individual flags
savvycal services create --name "My Service" --duration 30
# Inline JSON
savvycal services create --data '{"name": "My Service", "duration": 30}'
# JSON file
savvycal services create --data-file ./service.json| Flag | Description |
|---|---|
-o, --output <format> |
Output format: auto, json, raw, table (default: auto) |
--token <token> |
API token |
--account <id> |
Account ID (sent as X-SavvyCal-Account header) |
--base-url <url> |
API base URL |
| Format | Behavior |
|---|---|
auto |
table when stdout is a TTY, json when piped |
json |
Pretty-printed JSON |
table |
ASCII table (lists show columns; single resources show key/value pairs) |
raw |
String data as-is, or compact JSON |
savvycal services list # auto-detects format
savvycal services list -o json # force JSON
savvycal services list -o json | jq '.data[].name' # pipe-friendlyList tables include pagination info and prompt for the next page when applicable.
savvycal config get <key>
savvycal config set <key> <value>Valid keys: account, baseUrl, token, tokenType
Config is stored at ~/.config/savvycal/config.json with owner-only permissions.
pnpm dev # Run CLI from source (via tsx)
pnpm build # Compile to dist/
pnpm test # Run tests (vitest)
pnpm test:watch # Run tests in watch mode
pnpm typecheck # Type-check without emitting
pnpm lint # Lint
pnpm lint:fix # Auto-fix lint issuesCommands are generated from the live OpenAPI spec:
pnpm generateThis fetches the spec from https://api.savvycal.app/v1/spec and produces src/generated/commands.ts. The generator:
- Extracts resources and actions from operation IDs and paths
- Maps path parameters to positional arguments or required
--optionflags - Generates query and body parameter flags with type coercion
- Separates public and private endpoints
- Auto-formats the output with ESLint