# SmoothCapture CLI Reference

SmoothCapture can be driven by scripts and agents through `SmoothCapture cli`. The app binary doubles as the CLI client: it sends one JSON command over a local Unix socket to the running app, streams responses, and exits. Recording and export happen inside the app process (it holds the Screen Recording permission and the Metal render pipeline).

## Setup

The control server is **off by default**. Enable it one of three ways:

```bash
# One-time, persistent (also togglable in Settings -> General -> "Command-line control")
"/Applications/SmoothCapture.app/Contents/MacOS/SmoothCapture" cli enable

# Or per-launch, session-only
open -g -a SmoothCapture --args --enable-cli
```

Optional convenience symlink:

```bash
"/Applications/SmoothCapture.app/Contents/MacOS/SmoothCapture" cli install-symlink   # -> /usr/local/bin/smoothcapture
smoothcapture cli ping
```

If the app isn't running, any command auto-launches it in the background (requires the setting to be enabled) and retries for up to 20 s.

## Output contract

- The final **result** is a single JSON line on **stdout**: `{"id":"...","type":"result","data":{...}}`
- **Progress/events** go to stderr as human-readable text; pass `--json` to get them as JSON lines on stdout instead: `{"type":"event","event":"progress","data":{"progress":0.42,"fps":118}}`
- **Errors** are JSON on stderr (`{"type":"error","error":{"code":"...","message":"...","hint":"..."}}` with `--json`, readable text otherwise).

### Exit codes

| Code | Meaning |
|---|---|
| 0 | Success |
| 2 | Bad usage / unknown device or preset |
| 3 | Control server disabled (`SERVER_DISABLED`) |
| 4 | Missing macOS permission (`PERMISSION_*`) |
| 5 | Recording-state conflict (`ALREADY_RECORDING`, `NOT_RECORDING`) |
| 6 | Project/export failure |
| 7 | Could not connect / launch timeout |

### Error codes

`SERVER_DISABLED`, `PERMISSION_SCREEN_RECORDING`, `PERMISSION_ACCESSIBILITY`, `ALREADY_RECORDING`, `NOT_RECORDING`, `DEVICE_NOT_FOUND`, `PROJECT_NOT_FOUND`, `PROJECT_OPEN_IN_EDITOR`, `EXPORT_IN_PROGRESS`, `SESSION_BUSY`, `EXPORT_FAILED`, `BAD_REQUEST`, `INTERNAL`. Every error includes a `hint` when there's a useful next step.

`PERMISSION_SCREEN_RECORDING` means a **human** must grant Screen Recording to SmoothCapture once in System Settings -> Privacy & Security; the CLI cannot do it.

## Commands

### ping
```bash
smoothcapture cli ping
# -> {"version":"1.2.51","build":"57","bundleID":"...","protocolVersion":1,"pid":12345}
```

### status
Recording state, screen-recording permission, and the project currently open in the editor (if any).

### devices
Lists capture sources. Run this before `record start` to get real ids.
```bash
smoothcapture cli devices --json
# -> {"displays":[{"id":3,"width":1920,"height":1080,"frame":{...}}],
#    "windows":[{"id":5533,"title":"...","app":"Safari","bundleID":"com.apple.Safari","frame":{...}}],
#    "cameras":[{"id":"...","name":"MacBook Pro Camera"}],
#    "microphones":[{"id":"...","name":"MacBook Pro Microphone"}]}
```

### record start
```bash
smoothcapture cli record start --display 3                    # full display
smoothcapture cli record start --window 5533                  # one window
smoothcapture cli record start --display 3 --area 100,100,800,600   # region (display-local points)
```
Options: `--microphone <id|false>` `--camera <id|false>` `--system-audio` `--keyboard true|false` `--countdown <seconds>` (default 0 - starts immediately).

Defaults are deterministic: no microphone, no camera, no system audio, keyboard capture on (silently skipped with a `warnings` entry if Accessibility permission is missing). Omitting a target records the first display.

Cursor positions and clicks are always captured - they feed smart zoom.

### record stop
Stops, converts to a `.smoothcapture` project bundle, and returns its path. Emits a `finalizing` event first; conversion can take a few seconds.
```bash
smoothcapture cli record stop --json
# -> {"bundlePath":"/Users/you/Movies/SmoothCapture/....smoothcapture","videoPath":".../screen.mp4","duration":12.4}
```

### record status / record cancel
`status` -> `{isRecording, isStarting, isStopping, duration}`. `cancel` stops and **discards** all output.

### screenshot
Captures a still image at native pixel scale (retina) through the app's Screen Recording permission - no extra permission grant needed for the calling terminal.
```bash
smoothcapture cli screenshot --output shot.png                      # first display
smoothcapture cli screenshot --window 5533 --output window.png      # one window, tight bounds
smoothcapture cli screenshot --display 3 --area 100,100,800,600 --output region.png
smoothcapture cli screenshot --pretty --output hero.png             # marketing-ready treatment
# -> {"outputPath":"/.../hero.png","width":3840,"height":2160,"fileSize":1929919,"pretty":true}
```
Raw capture defaults: cursor hidden (`--cursor` to include it), window captures have tight bounds with transparent rounded corners (use PNG to keep them; JPEG flattens onto white).

`--pretty` applies SmoothCapture's signature look - background, padding, rounded corners, drop shadow - matching the video editor's defaults. Passing any styling flag implies `--pretty`:

- `--background <name>`: bundled background (e.g. `Gradient/20250901_Mac`, `Zen/1` - run `backgrounds` for the list), `Solid/RRGGBB` or `#RRGGBB` for a solid color, or an absolute image path. Default `Gradient/20250901_Mac`.
- `--padding 0.9`: image scale within the canvas - same semantics as `backgroundPadding` in project.json (`0.9` ~ 10% margin). Default 0.9.
- `--corner-radius 0.06`: fraction of the image's smaller dimension. Default 0.06.
- `--no-shadow`: disable the drop shadow (on by default in pretty mode).

Other options: `--format png|jpg` (also inferred from the output extension; default png), `--jpeg-quality 0.9`. Omitting `--output` writes to `~/Pictures/SmoothCapture/Screenshot <timestamp>.png`.

### backgrounds
Lists every bundled background name for `screenshot --background` and project.json's `selectedBackgroundImage`.
```bash
smoothcapture cli backgrounds --json
# -> {"backgrounds":[{"name":"Gradient/20250901_Mac","displayName":"September 1, 2025"},...]}
```

### project autozoom
Generates cinematic zoom effects from recorded clicks - the main "make it look good" step. Runs headless and saves the bundle.
```bash
smoothcapture cli project autozoom --path demo.smoothcapture
# -> {"zoomEffectsGenerated":4,"totalZoomEffects":4}
```
Options: `--clear-existing true|false` (default true), `--peak-zoom 2.0`, `--click-lead 0.3`, `--click-tail 2.5`, `--fill-gap 2.5`.
Returns 0 generated if the recording contained no clicks (nothing to zoom to).

### project apply-preset / project presets
Applies a saved editor preset (background, padding, cursor, webcam layout...) headlessly. Presets are created by a human in the editor's preset menu; `project presets` lists their names.

### project open / project reload
`open --path <bundle>` opens the editor UI on a project. `reload` forces the editor to re-read a project it already has open - required after editing `project.json` externally, otherwise the editor's autosave overwrites your changes.

### export
Headless export through the same Metal pipeline as the editor - output is identical to an in-app export.
```bash
smoothcapture cli export --path demo.smoothcapture --output demo.mp4 --preset 1080p30
# progress on stderr ... then:
# -> {"outputPath":"/.../demo.mp4","fileSize":645628,"duration":12.4}
```
- `--preset`: `Original`, `Original 30fps`, `1080p60`, `1080p30`, `4K60`, `4K30`
- Overrides: `--resolution WxH`, `--fps <n>`, `--bitrate <bps>`, `--codec h264|hevc|proRes422|proRes4444`, `--format mp4|mov|gif` (also inferred from the output extension), `--transparent`
- Fails with `PROJECT_OPEN_IN_EDITOR` if the same bundle is open in the editor (close it first).
- Subtitles are not rendered in headless exports.

## Rules of engagement

1. One recording and one headless project operation at a time.
2. Never edit `project.json` while the project is open in the editor without calling `project reload` immediately after.
3. Fine-grained effect edits (backgrounds, aspect ratio, individual zooms...) are done by editing `project.json` directly - see [project-json-reference.md](project-json-reference.md).
4. The end-to-end recipe lives in [demo-video-workflow.md](demo-video-workflow.md).
