# CLI commands

> Every scribiz command, what it prints and where it writes, and the exit codes a script can rely on.

Page: https://scribiz.com/docs/cli/commands

```text
scribiz <input>... [flags]
scribiz context <input>... [flags]
scribiz ask <input|result.json> "<question>" [flags]
scribiz format <result.json|-> --format <format> [flags]
scribiz login | logout | whoami
scribiz setup
scribiz doctor [--jit]
scribiz mcp [--allow-files] [--root <dir>]... [--allow-private-network]
scribiz help [command]
scribiz --json-schema
```

`<input>` is a link, a file or a folder. Every flag is listed on [Flags](https://scribiz.com/docs/cli/flags.md). `scribiz help` and `scribiz help <command>` print the same text as `--help`.

An empty argument is an error, with exit code 2 and the message `Missing input`. It is never read as the current folder, so `scribiz "$URL"` with `$URL` unset in a script does not transcribe every file next to it. To run the current folder, write `.` (a dot).

> [!TIP]
> Quote a link that contains `?` or `&`. zsh, the default shell on a Mac, reads `?` as a wildcard and stops with `no matches found`. The short form `https://youtu.be/jNQXAC9IVRw` needs no quotes.

## `scribiz <input>`

Transcribe a link, a file or a folder.

```console
$ scribiz speech.mp3
✓ Looked up the video  0.0s
• Plan: audio · under $0.01
  Listening to the audio. Transcript only: no summary.
✓ Extracted the audio  0.1s
✓ Split the audio · 1 chunk, 9 s of speech  0.0s
✓ Listened · 1 chunk  3.9s
✓ Checked coverage · 0 of 1 chunks need repair  0.0s
– Repaired gaps skipped · every chunk passed the coverage gate
1
00:00:00,300 --> 00:00:02,418
Welcome to the Scribus fixture test.

2
00:00:02,600 --> 00:00:03,800
My name is Samantha.
...
✓ Done in 4.0s · 31 words · 0:12 of video · 0.2 min · $0.0011
```

Progress goes to standard error. The result goes to standard output, so a pipe or a redirect gets only the result. The plan, with an estimate of the cost, is printed before work starts. `--max-cost` stops the run when the estimate is over a limit.

- **One input.** The result goes to standard output. With `-o`, it goes to a file (the path has an extension) or into a folder (the path has none, ends with `/`, or already exists as a folder).
- **Several inputs, or a folder.** Each input gets its own file, named `<name>.<format>` and written next to the source, or in the `-o` folder, or in the current folder for links. `-o` must be a folder. The paths are printed on standard output. The `context` format is written as `<name>.context.md`. A name Scribiz picks itself never replaces a file that is already there: it writes `talk-2.srt` instead. A path you name with `-o` is yours to replace.
- **The format** is SRT unless you pass `--format`. SRT, VTT and TXT ask only for the transcript, which costs less and writes no summary. `md`, `context` and `json`, and any run with `--visual` or `--mode full` or `visual`, build the whole Context.
- **A video with no audio** stops with `NO_AUDIO_STREAM` and exit code 4. Use `scribiz context ./clip.mov --mode watch` for those.

### Folders

Give it a folder and it works through the media files inside, one level deep. In a terminal you get a picker, and files that already have a `.srt` next to them are marked. With `--json`, `--no-input` or no terminal, it processes every file. A failure on one file does not stop the others, and the exit code is the first failure's. An account problem (`AUTH` or `QUOTA`) stops the rest, because the next file would fail the same way.

### When a word is also a file

The subcommands (`context`, `ask`, `format`, `login`, `logout`, `whoami`, `setup`, `doctor`, `mcp`) apply only when no file or folder has that name. If you have a folder called `context`, `scribiz context` transcribes it and prints a one-line hint. Put `--` before an input to force it:

```bash
scribiz -- context
```

## `scribiz context <input>`

Build the whole Context: transcript, on-screen notes, summary, chapters and key moments. The default format is `context`, Markdown for an agent. It prints to standard output so you can pipe it.

```bash
scribiz context https://youtu.be/jNQXAC9IVRw
scribiz context ./lecture.mp4 --visual --format json -o lecture.json
```

```console
$ scribiz context https://youtu.be/jNQXAC9IVRw
✓ Looked up the video  4.8s
• Plan: captions → synthesis · < $0.01 to $0.02
  Captions first; listening to the audio only if they are missing or unusable.
✓ Downloaded · manual en captions, 6 segments  0.8s
– Watched skipped · normal speech density
✓ Wrote the summary  2.7s
---
title: "Me at the zoo"
source: "https://www.youtube.com/watch?v=jNQXAC9IVRw"
channel: "jawed"
published: "2005-04-24"
duration: "00:19"
...
✓ Done in 8.3s · 39 words · 0:19 of video · <0.1 min · $0.0018
```

`--visual` adds the on-screen layer to a run that listens. The full output is on [Output formats](https://scribiz.com/docs/cli/formats.md#context).

## `scribiz ask <input> "<question>"`

Ask a question about a video. The answer comes back with the moments that support it, each with a time. The words after the input are joined into the question.

```console
$ scribiz ask zoo.json "What does the speaker say about the elephants?"
✓ Answered  1.6s
The speaker says that the cool thing about elephants is that they have really, really long trunks.

Sources
  [00:05-00:14] the cool thing about these guys is that they have really... really really long trunks and that's cool
✓ Done in 1.6s · 0:19 of video · 0.1 min · $0.0007
```

The input can be a link, a file, or a `.json` Context you saved with `--format json` or `--json --out-file`. A saved Context is asked without running the video again. A link or a file is read first, and cached afterwards. If the question is about something that was shown, Scribiz runs the on-screen layer for it. A question costs 0.1 minutes on a Scribiz account. `--format json` prints `{ "answer": ..., "citations": [...] }`.

## `scribiz format <result.json>`

Render a Context you already saved, without fetching anything. It needs no credential and no network.

```bash
scribiz format lecture.json --format srt -o lecture.srt
scribiz format lecture.json --format txt --speakers
scribiz https://youtu.be/jNQXAC9IVRw --json | tail -n 1 | scribiz format - --format vtt
```

`-` reads standard input. It accepts the file `--json --out-file` wrote, a `--format json` file, or the inline `result` line a `--json` run prints. `--offset` shifts subtitle times and `--speakers` or `--no-speakers` decides whether speakers are labeled. See [Output formats](https://scribiz.com/docs/cli/formats.md).

## `scribiz login`

Sign in to a free Scribiz account. A free account has 30 minutes a month.

```bash
scribiz login
scribiz login --no-browser
scribiz login --key
```

`login` asks Scribiz for a code and shows it with a link. You confirm the code at `https://scribiz.com/login/device`, signed in to your Scribiz account, and the CLI saves a Scribiz key to `~/.scribiz/config.json`. In a terminal it opens the link for you. `--no-browser` only prints it.

```console
$ scribiz login
┌  scribiz login
│
●  Open https://scribiz.com/login/device?user_code=ABCD1234
│  and confirm the code ABCD1234
Waiting for you to approve in the browser (Ctrl+C to cancel)...
│
◆  Signed in as you@example.com (free plan). Key sbz_live_…Q7xK saved to /Users/you/.scribiz/config.json
│
●  Runs with this sign-in send your audio to Scribiz, which sends it to Google. `scribiz whoami` shows your minutes.
│
└  Try: scribiz "https://www.youtube.com/watch?v=jNQXAC9IVRw"
```

A code expires after 10 minutes. `login` then stops with `The sign-in code expired` and exit code 3. If you press Deny in the browser, it stops with `Sign-in was denied in the browser` and the same exit code. Run it again for a new code. An account can hold up to 10 keys: at the limit, revoke one in the dashboard first.

- `--key` skips the browser. It asks for a Scribiz key (one line on standard input also works) made in the [dashboard](https://scribiz.com/dashboard), and saves it. Use it on a server or over SSH. A key that does not start with `sbz_` is refused.
- `--json` prints a `device_code` message with the code and the links, then the result. See [The JSON protocol](https://scribiz.com/docs/cli/json-protocol.md#signing-in).
- `--client <id>` is the client id sent to the device flow. It must be `scribiz-cli` (the default), `scribiz-mac` or `scribiz-mcp`. Any other value fails with `Invalid client ID` and exit code 5. You do not need it.

`login` replaces a saved Gemini key: the file holds one credential. If `GEMINI_API_KEY` is set in your environment, it still wins over the saved sign-in, and `login` says so at the end. See [Authentication](https://scribiz.com/docs/authentication.md#which-credential-wins).

## `scribiz logout`

Removes the saved Scribiz sign-in and the saved Gemini key from `~/.scribiz/config.json`.

```console
$ scribiz logout
Removed the Scribiz login from /Users/you/.scribiz/config.json. The key itself still works until you revoke it at https://scribiz.com/dashboard: nothing was sent to Scribiz.
```

`logout` works on this machine only. It does not revoke the Scribiz key and it does not tell Scribiz, so the key stays valid until you revoke it in the [dashboard](https://scribiz.com/dashboard). A `SCRIBIZ_API_KEY` or `GEMINI_API_KEY` in your environment is not touched, and `logout` tells you when one is still set. With nothing saved it says `Nothing saved in` the path of the file.

## `scribiz whoami`

Shows which credential a run will use and where it comes from.

```console
$ scribiz whoami
you@example.com
Plan: free · 30 min left of 30 included, resets 2026-11-01
Key: sbz_live_…Q7xK (from config, scope all)
API: https://scribiz.com/api
```

With a Scribiz key it asks Scribiz who the key belongs to, and prints the plan, the minutes left and the day they reset. With your own Gemini key it says so and asks nobody:

```console
$ scribiz whoami
Using your own Gemini key (AIza…WXYZ, from config). Not signed in to Scribiz.
```

When `GEMINI_API_KEY` is set and a sign-in is also saved, `whoami` names the one a run uses:

```console
$ scribiz whoami
Using your own Gemini key (AIza…WXYZ, from GEMINI_API_KEY). Your saved Scribiz sign-in (sbz_live_…Q7xK) is not used while GEMINI_API_KEY is set: unset it to use your Scribiz minutes.
```

With no credential it fails with `No credential found` and exit code 3, and says to run `scribiz login` or `scribiz setup`.

## `scribiz setup`

Use your own Gemini key instead of an account. It asks for the key, checks it with Google, and saves it to the config file with mode 0600. It replaces a saved Scribiz sign-in. Without a terminal, pipe the key in: `echo "$KEY" | scribiz setup`. It refuses a key that starts with `sbz_` before it contacts Google, and points you to `scribiz login --key`. See [Authentication](https://scribiz.com/docs/authentication.md#use-your-own-gemini-key).

## `scribiz doctor`

Check your tools, your credential and your versions. See [Install the CLI](https://scribiz.com/docs/cli.md#check-your-setup). It exits 3 when the credential is missing or rejected. `--jit` is a speed self-test for a compiled binary. Under the npm package, which runs on Node, it prints that it does not apply and exits 0.

## `scribiz mcp`

Start the MCP server on standard input and output, for a client that launches it as a command.

```bash
claude mcp add scribiz -- scribiz mcp
scribiz mcp --allow-files --root ~/Videos
```

Local file paths are refused unless you pass `--allow-files`. Then only files under a `--root` folder are read. Repeat `--root` for more than one folder. Without `--root`, the current folder is the one allowed folder, except `/`, your home folder or a folder above it: a client that starts the server in one of those must pass `--root`. `--root` without `--allow-files` is an error.

Links to your own machine and to private networks (`localhost`, `192.168.x.x`, `*.local`, a cloud metadata address) are refused, because the model that calls the server may have read a page that told it to fetch one. So are pages that only the generic reader of `yt-dlp` handles. Direct media links, YouTube, Instagram, TikTok, Vimeo and X work. `--allow-private-network` lifts both rules.

The server reads the same credential as every other command: `SCRIBIZ_API_KEY`, `GEMINI_API_KEY`, or what `scribiz login` or `scribiz setup` saved. It takes the `watch` argument and serves stored on-screen notes: see [Connection modes](https://scribiz.com/docs/mcp/connection-modes.md#local). Standard output carries only protocol messages. A ready line goes to standard error. See [MCP install](https://scribiz.com/docs/mcp/install.md).

## Machine-readable output

`--json` turns standard output into newline-delimited JSON messages and implies `--no-input`. `scribiz --json-schema` prints one JSON document with a JSON Schema for the Context, the progress events and every message, so you can generate types. The full contract is in [The JSON protocol](https://scribiz.com/docs/cli/json-protocol.md).

## Exit codes

| Code | Meaning |
| --- | --- |
| 0 | Done |
| 1 | Something went wrong that none of the codes below describe |
| 2 | Wrong usage: a bad flag or a missing argument |
| 3 | Credentials or minutes: no key, a bad key, or out of minutes |
| 4 | The source: not found, private, blocked, live, too long, unreadable |
| 5 | The service: Google or Scribiz had a problem, a rate limit or a timeout |
| 6 | A required tool is missing: `ffmpeg` or `ffprobe`, or `yt-dlp` for a link that needs it |
| 130 | Canceled with Ctrl+C or SIGTERM |

If the reader of standard output goes away, for example `scribiz ... | head`, the CLI stops quietly and exits 0. The error codes behind these are on [Errors and limits](https://scribiz.com/docs/api/errors.md#error-codes).

---

Checked against the Scribiz build on 2026-10-05.
