# TypeScript SDK

> Install, credentials, and every method next to its API call.

```bash
npm install @trykubi/sdk
```

```ts
import { Kubi } from "@trykubi/sdk";

const client = new Kubi();           // key from KUBI_API_KEY
const screen = client.screen("scr_7f2kq9w3x8m4b6tzp1ac");
const shot = await screen.screenshot();
await screen.click({ x: 450, y: 280, screenshot_id: shot.screenshot_id });
```

## Credentials

The client looks for a key in this order: the `apiKey` you pass in code, then `KUBI_API_KEY`. It labels every call with a `Kubi-Run` header (from `KUBI_RUN`, else Claude Code's session id, else one id per client), so the screen's history groups your calls into runs.

## Safe by default

- Every POST gets an `Idempotency-Key`, so a retried click never clicks twice.
- It retries only errors marked `retryable`, and never `504 OUTCOME_UNKNOWN`.
- `client.screen()` with no id uses your only screen, and errors with the list when you have several.

## Methods

| SDK | API | Permission |
|---|---|---|
| `client.screens.list()` | `GET /screens` | read |
| `client.screens.create()` | `POST /screens` | power |
| `screen.get()`, `.update()`, `.delete()` | `GET`, `PATCH`, `DELETE /screens/{id}` | read, power |
| `screen.start()`, `.stop()`, `.restart()` | `POST /screens/{id}/start` and so on | power |
| `screen.convert({ kind })` | `POST /screens/{id}/convert` | power |
| `client.templates.list()`, `.get(id)` | `GET /templates`, `/templates/{id}` | read |
| `client.templates.create()`, `.delete(id)` | `POST /templates`, `DELETE /templates/{id}` | power |
| `client.operations.wait(id)` | `GET /operations/{id}` | read |
| `screen.screenshot()`, `.screenshotImage()` | `GET /screens/{id}/screenshot` | read |
| `screen.click()`, `.type()`, `.press()` | `POST /screens/{id}/click`, `/type`, `/press` | control |
| `screen.scroll()`, `.drag()`, `.move()` | `POST /screens/{id}/scroll`, `/drag`, `/move` | control |
| `screen.act([...])` | `POST /screens/{id}/actions` | control |
| `screen.exec()`, `.execs.get()`, `.execs.kill()` | `/screens/{id}/exec` | exec |
| `screen.files.upload()`, `.download()`, `.list()` | `/screens/{id}/files`, `/dir` | exec |
| `screen.viewerLink()` | `POST /screens/{id}/viewer` | read |
| `screen.history.list()`, `.screenshot(id)` | `GET /screens/{id}/history`, `/screenshots/{id}` | read |
| `client.me()` | `GET /me` | read |

A Python SDK generated from the same spec comes later.
