# CLI

> Sign in, render JSON files to PDF or PNG, browse templates, check usage and manage API keys from the terminal with quirepdf-cli.

```bash
npx quirepdf-cli login you@example.com
npx quirepdf-cli render order.json
```

```text
→ We sent a sign-in link to you@example.com.
  Open it and enter this code: 482 913
  Waiting… (Ctrl+C to cancel)
✓ Logged in as you@example.com. Key saved to ~/.config/quire/config.json
✓ wrote order.pdf (1 page, 29 KB) · template document (fallback) · 10.4 ms · 19/20 renders left this month
```

The CLI needs Node.js 18 or later and has no dependencies. Run it with `npx quirepdf-cli`, or install it once to get the `quirepdf` command:

```bash
npm install -g quirepdf-cli
quirepdf render order.json
```

The examples below use `quirepdf`.

## Commands

| Command | What it does |
|---|---|
| `quirepdf login [email]` | Sign in with an email link and a code, and save your API key |
| `quirepdf render [file \| -]` | Render a JSON file (or stdin) to PDF or PNG |
| `quirepdf templates [name]` | List templates, or show one template's fields |
| `quirepdf usage` | Your plan and renders used this month |
| `quirepdf keys` | List keys; `keys create [name]`, `keys revoke <id>` |
| `quirepdf upgrade [starter \| pro \| scale]` | Show plans, or open checkout for one |
| `quirepdf billing` | Open the billing portal: change plan, cancel, update card, invoices |
| `quirepdf logout` | Delete the saved key from this machine |

Add `--json` to any command for machine-readable output.

## Sign in

```bash
quirepdf login you@example.com
```

Quire emails you a sign-in link and the CLI shows a 6-digit code. Open the link, enter the code and approve. The CLI waits up to 15 minutes, then saves the new key to `~/.config/quire/config.json` with permissions 600. Without an email argument, the CLI asks for one. With `--json`, the code and instructions go to stderr so stdout stays a single JSON object.

The first sign-in creates your account on the free plan. If the saved key still works, `login` tells you who you're signed in as and creates nothing; add `--force` to sign in again. Each new sign-in adds a key named after this machine (`quirepdf-cli on your-laptop`), and the old keys keep working until you revoke them.

`quirepdf logout` deletes the saved file. The key itself stays valid until you run `quirepdf keys revoke <id>`.

## Render

```bash
quirepdf render invoice.json                 # → invoice.pdf, template auto-detected
quirepdf render invoice.json -t invoice      # require the invoice template
quirepdf render invoice.json -o out/inv.pdf  # choose the output path
quirepdf render report.json --png --page 2   # → report-p2.png
quirepdf render invoice.json --open          # open the file when done
cat order.json | quirepdf render - -o order.pdf
```

| Option | Meaning |
|---|---|
| `-t, --template <name>` | Use this template and validate strictly against it. Default: auto-detect. |
| `-o, --out <path>` | Output file. Default: the input name with `.pdf`, or `-p<N>.png` for PNG. From stdin: `document.pdf`. |
| `--png` | Render one page as PNG instead of a PDF |
| `--page <N>` | The page to render with `--png` (default 1) |
| `--open` | Open the result with your system's default app |
| `--test` | Free test render: watermarked, not counted, works after the quota runs out |
| `--json` | Print a JSON summary instead of the status line |

The CLI checks that the file is valid JSON before sending it. When your data falls back to the generic layout but nearly matched a template, it prints a tip:

```text
✓ wrote order.pdf (1 page, 37 KB) · template document (fallback) · 9.7 ms
  tip: almost matched invoice (seller is required); fix that to get the specialised layout
```

Invalid data prints every problem:

```text
✗ data has 2 problems
  • seller is required
  • items[0].qty must be a number
  See the expected fields with `quirepdf templates <name>`.
```

## Templates

```bash
quirepdf templates                            # list all seven
quirepdf templates receipt                    # required and optional fields
quirepdf templates receipt --sample > r.json  # a complete, valid example
quirepdf templates receipt --schema           # the JSON Schema
```

The quickest way to learn a template is to print its sample, edit it and render it.

## Usage and keys

```bash
quirepdf usage
quirepdf keys
quirepdf keys create ci
quirepdf keys revoke key_nb6N6M2qmGo7
```

`keys create` prints the new secret once; copy it then. `keys` marks the key the CLI is using with "(this key)". You can't revoke your only active key. See [Accounts and billing](/docs/accounts-and-billing).

## Upgrade

```bash
quirepdf upgrade        # list plans and prices
quirepdf upgrade pro    # open hosted checkout in your browser
```

Your plan changes as soon as payment completes. Add `--no-open` to print the checkout URL without opening a browser.

```bash
quirepdf billing        # open the billing portal: change plan, cancel, card, invoices
```

Once you're on a paid plan, change plans or cancel from `billing`; `upgrade` won't start a second subscription.

## CI and scripts

```bash
export QUIRE_API_KEY=qk_live_...
quirepdf render invoice.json --json
```

```json
{"file":"invoice.pdf","bytes":27559,"pages":1,"template":"invoice","source":"detected","render_ms":6.1,"quota_remaining":1873,"quota_limit":2000}
```

| Variable | Meaning |
|---|---|
| `QUIRE_API_KEY` | Use this key instead of the saved one. Recommended for CI and agents. |
| `QUIRE_API_URL` | API base URL. Default `https://api.quirepdf.dev`. |
| `QUIRE_CONFIG_DIR` | Where the config file lives. Default `~/.config/quire` (or `$XDG_CONFIG_HOME/quire`). |
| `NO_COLOR` | Turn off coloured output |

Exit codes:

| Code | Meaning |
|---|---|
| `0` | Success |
| `1` | API or data error; the message and every field problem are printed |
| `2` | Bad usage, such as an unknown command or a missing file argument |