|
1 | | -# BeatAPI CLI |
| 1 | +# BeatAPI CLI and TypeScript Client |
2 | 2 |
|
3 | | -A dependency-free Node.js command-line client for BeatAPI's public asynchronous |
4 | | -video workflows. |
| 3 | +Official command-line interface and TypeScript client for BeatAPI's public |
| 4 | +asynchronous AI video workflows. |
5 | 5 |
|
6 | | -This is an MVP scaffold. It is local-only and marked `private` until command |
7 | | -behavior, package naming, authentication UX, and release ownership are reviewed. |
| 6 | +The repository contains two independently publishable npm packages: |
8 | 7 |
|
9 | | -## Requirements |
| 8 | +- [`beatapi`](./packages/cli) — a human-, script-, and agent-friendly CLI. |
| 9 | +- [`beatapi-client`](./packages/client) — the typed runtime client shared by the |
| 10 | + CLI and the BeatAPI Codex plugin. |
10 | 11 |
|
11 | | -- Node.js 20 or newer |
12 | | -- `BEATAPI_API_KEY` for authenticated commands |
| 12 | +Both packages are generated and tested against the reviewed OpenAPI snapshot in |
| 13 | +[`contract/beatapi.openapi.yaml`](./contract/beatapi.openapi.yaml). The lock file |
| 14 | +records the exact source commit and SHA-256 digest. |
| 15 | + |
| 16 | +## Install the CLI |
| 17 | + |
| 18 | +Node.js 20.19+ or 22.12+ is required. |
| 19 | + |
| 20 | +```bash |
| 21 | +npm install --global beatapi |
| 22 | +beatapi auth login |
| 23 | +``` |
| 24 | + |
| 25 | +`auth login` reads the API key through hidden terminal input, validates it with |
| 26 | +`GET /v1/usage`, and saves it in the operating system credential manager. |
| 27 | + |
| 28 | +For CI, containers, or short-lived shells: |
13 | 29 |
|
14 | 30 | ```bash |
15 | 31 | export BEATAPI_API_KEY="sk_your_key" |
16 | | -npm link |
17 | | -beatapi --help |
| 32 | +beatapi auth status |
18 | 33 | ``` |
19 | 34 |
|
20 | | -## Commands |
| 35 | +Environment credentials take precedence over a saved credential. The CLI does |
| 36 | +not accept API keys as command-line arguments and never prints the key. |
| 37 | + |
| 38 | +## Five-minute workflow |
| 39 | + |
| 40 | +Create `music-video.json`: |
| 41 | + |
| 42 | +```json |
| 43 | +{ |
| 44 | + "images": ["https://media.example.com/reference.png"], |
| 45 | + "audio_url": "https://media.example.com/song.mp3", |
| 46 | + "prompt": "Cinematic nighttime performance with light trails.", |
| 47 | + "language": "en", |
| 48 | + "resolution": "720p", |
| 49 | + "compose_mode": "auto" |
| 50 | +} |
| 51 | +``` |
| 52 | + |
| 53 | +Then create and follow the task: |
21 | 54 |
|
22 | 55 | ```bash |
23 | | -beatapi workflows |
| 56 | +beatapi music-video create --file music-video.json |
| 57 | +beatapi tasks wait task_123 --interval 7000 |
| 58 | +``` |
| 59 | + |
| 60 | +Command results are formatted JSON on stdout. Polling progress and errors use |
| 61 | +stderr, so output can be piped to `jq`, saved, or consumed by automation. |
| 62 | + |
| 63 | +## Command reference |
| 64 | + |
| 65 | +```text |
| 66 | +beatapi auth login |
| 67 | +beatapi auth status |
| 68 | +beatapi auth logout |
| 69 | +
|
| 70 | +beatapi workflows list |
24 | 71 | beatapi usage |
25 | | -beatapi file upload ./input.mp3 |
26 | | -beatapi music-video create --json ./music-video.json |
27 | | -beatapi ecommerce-video create --json ./ecommerce-video.json |
28 | | -beatapi task get task_123 |
29 | | -beatapi task wait task_123 --interval 7000 --attempts 120 |
| 72 | +beatapi files upload ./input.mp3 |
| 73 | +
|
| 74 | +beatapi music-video create --file ./music-video.json |
| 75 | +beatapi music-video shots edit TASK SHOT --prompt "New direction" |
| 76 | +beatapi music-video shots edit TASK SHOT --file ./shot-edit.json |
| 77 | +beatapi music-video shots media TASK SHOT |
| 78 | +beatapi music-video compose TASK --shot SHOT_1 --shot SHOT_2 |
| 79 | +
|
| 80 | +beatapi ecommerce-video create --file ./ecommerce-video.json |
| 81 | +
|
| 82 | +beatapi tasks get TASK |
| 83 | +beatapi tasks wait TASK --interval 7000 --attempts 120 |
| 84 | +
|
| 85 | +beatapi webhooks list |
| 86 | +beatapi webhooks create --file ./webhook.json |
| 87 | +beatapi webhooks get WEBHOOK |
| 88 | +beatapi webhooks update WEBHOOK --file ./webhook-update.json |
| 89 | +beatapi webhooks delete WEBHOOK |
30 | 90 | ``` |
31 | 91 |
|
32 | | -Task creation JSON follows the canonical public contract at |
33 | | -`../beatapi-examples/openapi/beatapi.yaml`. |
| 92 | +Use `beatapi --help` for the installed command summary. `--json` remains an |
| 93 | +alias for `--file` on JSON-input commands. |
34 | 94 |
|
35 | | -The CLI writes machine-readable result JSON to stdout. Polling progress and |
36 | | -errors go to stderr so commands can be used in scripts. |
| 95 | +## TypeScript client |
37 | 96 |
|
38 | | -## Development |
| 97 | +```bash |
| 98 | +npm install beatapi-client |
| 99 | +``` |
| 100 | + |
| 101 | +```ts |
| 102 | +import { BeatAPIClient, BeatAPIError } from "beatapi-client"; |
| 103 | + |
| 104 | +const beatapi = new BeatAPIClient({ |
| 105 | + apiKey: process.env.BEATAPI_API_KEY, |
| 106 | +}); |
| 107 | + |
| 108 | +try { |
| 109 | + const task = await beatapi.createEcommerceVideoTask({ |
| 110 | + images: ["https://media.example.com/product.png"], |
| 111 | + duration: 15, |
| 112 | + prompt: "Fast vertical product launch ad.", |
| 113 | + aspect_ratio: "9:16", |
| 114 | + }); |
| 115 | + |
| 116 | + const result = await beatapi.waitForTask(task.id, { |
| 117 | + intervalMs: 7_000, |
| 118 | + onUpdate: ({ status }) => console.error(status), |
| 119 | + }); |
| 120 | + |
| 121 | + console.log(result.output?.media); |
| 122 | +} catch (error) { |
| 123 | + if (error instanceof BeatAPIError) { |
| 124 | + console.error(error.code, error.requestId); |
| 125 | + } |
| 126 | + throw error; |
| 127 | +} |
| 128 | +``` |
| 129 | + |
| 130 | +The client exposes every launch-contract operation: workflows, usage, file |
| 131 | +upload, music-video automatic and manual composition, ecommerce-video tasks, |
| 132 | +task polling, and webhook CRUD. |
| 133 | + |
| 134 | +Retries are bounded and opt-in through method retry options. The client |
| 135 | +preserves BeatAPI error code, HTTP status, request ID, details, and |
| 136 | +`Retry-After` information. |
| 137 | + |
| 138 | +## Security model |
| 139 | + |
| 140 | +- API keys are read from `BEATAPI_API_KEY` or an OS credential manager. |
| 141 | +- macOS forces the native Keychain backend, Windows uses Credential Manager, |
| 142 | + and Linux uses Secret Service. |
| 143 | +- Unsupported systems fail closed and instruct the user to use the environment |
| 144 | + variable; the CLI does not fall back to plaintext or file-based storage. |
| 145 | +- API keys must never be committed, placed in JSON input files, pasted into |
| 146 | + issue reports, or passed as command arguments. |
| 147 | +- Webhook signing secrets are returned once by the API and should be stored |
| 148 | + with the same care as an API key. |
| 149 | + |
| 150 | +See [SECURITY.md](./SECURITY.md) for reporting instructions. |
| 151 | + |
| 152 | +## Contract and development |
39 | 153 |
|
40 | 154 | ```bash |
41 | | -npm run check |
| 155 | +npm ci |
| 156 | +npm run contract:check |
| 157 | +npm run check:generated |
42 | 158 | npm test |
| 159 | +npm run verify |
43 | 160 | ``` |
44 | 161 |
|
| 162 | +Important scripts: |
| 163 | + |
| 164 | +- `npm run contract:sync` copies the reviewed public contract snapshot. |
| 165 | +- `npm run generate:types` regenerates TypeScript definitions. |
| 166 | +- `npm run check:generated` proves generated definitions are current. |
| 167 | +- `npm run verify` runs contract, type, test, build, and package checks. |
| 168 | + |
| 169 | +The canonical private contract is maintained in the BeatAPI product repository. |
| 170 | +This public repository contains only its reviewed, publication-safe snapshot. |
| 171 | +See [CONTRIBUTING.md](./CONTRIBUTING.md) before changing behavior. |
| 172 | + |
| 173 | +## Publishing |
| 174 | + |
| 175 | +GitHub Actions verifies every pull request. Publishing is triggered by a GitHub |
| 176 | +release or manually through the release workflow after the repository |
| 177 | +environment contains an `NPM_TOKEN` secret. |
| 178 | + |
| 179 | +Release steps and ownership prerequisites are documented in |
| 180 | +[`docs/releasing.md`](./docs/releasing.md). |
| 181 | + |
| 182 | +## License |
| 183 | + |
| 184 | +MIT |
0 commit comments