# The CLI

nokap includes a command-line interface for capturing screenshots and PDFs without writing Python. The CLI exposes the same capabilities as the Python API through five commands, making it easy to integrate nokap into shell scripts, Makefiles, and CI pipelines. All screenshot and PDF options are available as command-line flags with sensible defaults.

## Overview

| Command | Purpose |
|----|----|
| `nokap webshot` | Capture a URL or local file as an image or PDF |
| `nokap from-html` | Render an HTML file to an image or PDF |
| `nokap doctor` | Run full diagnostics (launch Chrome, test captures) |
| `nokap batch` | Process multiple capture jobs from a JSON manifest |
| `nokap install-chrome` | Download `chrome-headless-shell` into nokap's cache |

There are also two informational commands: `nokap info` (quick system check) and `nokap --version`.

## Installation

The CLI is installed automatically with the package:

``` bash
pip install nokap
nokap --version
```

## `nokap webshot`

The primary command. It takes a URL (or local file path) and produces a screenshot or PDF, depending on the output file extension. This is the command you'll reach for most often, whether you're grabbing a quick screenshot from the terminal or building capture steps into a CI pipeline.

``` bash
nokap webshot [OPTIONS] URL [FILE]
```

### Arguments

| Argument | Description                       | Default       |
|----------|-----------------------------------|---------------|
| `URL`    | URL or local file path to capture | *(required)*  |
| `FILE`   | Output file path                  | `webshot.png` |

The format is determined by the file extension: `.png`, `.jpg`, or `.webp` for raster images; `.pdf` for PDF. If you omit `FILE`, it defaults to `webshot.png` in the current directory.

### Options

| Option | Short | Description | Default |
|----|----|----|----|
| `--vwidth` |  | Viewport width in pixels | `992` |
| `--vheight` |  | Viewport height in pixels | `744` |
| `--selector` | `-s` | CSS selector to capture | *(full page)* |
| `--expand` | `-e` | Pixels to expand around selector | `0` |
| `--delay` | `-d` | Seconds to wait after page load | `0.2` |
| `--zoom` | `-z` | Zoom/scale factor | `1.0` |
| `--useragent` |  | Custom User-Agent string | *(Chrome default)* |
| `--page-size` |  | Paper size for PDF output | `letter` |
| `--landscape` |  | Use landscape orientation (PDF) | *(flag)* |
| `--print-background` |  | Print CSS backgrounds (PDF) | *(flag)* |

### Examples

Capture a basic screenshot (defaults to PNG at 992×744 viewport):

``` bash
nokap webshot https://example.com screenshot.png
```

Target a specific element with a CSS selector. nokap will automatically crop the output to just that element's bounding box:

``` bash
nokap webshot https://example.com header.png -s "h1"
```

Combine a selector with zoom and expand for a presentation-ready capture with padding and Retina resolution:

``` bash
nokap webshot page.html table.png -s "table" -z 2 -e 10
```

Simulate a mobile viewport by setting custom dimensions:

``` bash
nokap webshot https://example.com mobile.png --vwidth 375 --vheight 812
```

Generate a PDF. The output format is determined entirely by the file extension:

``` bash
nokap webshot https://example.com doc.pdf --page-size a4
```

Landscape orientation with CSS backgrounds printed (useful for styled dashboards or reports):

``` bash
nokap webshot report.html report.pdf --landscape --print-background
```

Add a delay for pages with lazy-loaded content or animations that need time to settle:

``` bash
nokap webshot https://example.com animated.png -d 2.0
```

Capture a local HTML file (paths are resolved relative to the current directory):

``` bash
nokap webshot ./build/index.html output.png
```

## `nokap from-html`

Renders an HTML file to an image or PDF. This is the CLI equivalent of [nokap.from_html()](../reference/from_html.md#nokap.from_html) in Python. The key difference from [webshot](../reference/webshot.md#nokap.webshot) is that `from-html` defaults to `selector="html"` (captures the full rendered document rather than the viewport), making it the natural choice for HTML files generated by packages like Great Tables or report builders.

``` bash
nokap from-html [OPTIONS] HTML_FILE [FILE]
```

### Arguments

| Argument    | Description                    | Default       |
|-------------|--------------------------------|---------------|
| `HTML_FILE` | Path to an HTML file to render | *(required)*  |
| `FILE`      | Output file path               | `webshot.png` |

### Options

| Option       | Short | Description                      | Default |
|--------------|-------|----------------------------------|---------|
| `--selector` | `-s`  | CSS selector to capture          | `html`  |
| `--vwidth`   |       | Viewport width in pixels         | `992`   |
| `--vheight`  |       | Viewport height in pixels        | `744`   |
| `--expand`   | `-e`  | Pixels to expand around selector | `0`     |
| `--delay`    | `-d`  | Seconds to wait after page load  | `0.2`   |
| `--zoom`     | `-z`  | Zoom/scale factor                | `1.0`   |

### Examples

Render a full HTML page to PNG. Since the default selector is `html`, the entire document is captured regardless of viewport height:

``` bash
nokap from-html report.html report.png
```

Capture just a specific element from the page. This is especially useful when your HTML file contains a styled table surrounded by boilerplate:

``` bash
nokap from-html data.html table.png -s "table" -z 2
```

Add breathing room around the element with `--expand`:

``` bash
nokap from-html chart.html chart.png -s "#chart" -e 20
```

Generate a PDF from an HTML file. When combined with a selector, nokap produces an element-bounded PDF sized exactly to the element (perfect for embedding tables in presentations):

``` bash
nokap from-html invoice.html invoice.pdf
nokap from-html gt_table.html table.pdf -s "table" -e 5
```

### Typical Workflow: Great Tables → PDF

A common pattern is generating an HTML table with Great Tables, then using `from-html` to convert it to a tight-fit PDF for slides:

``` bash
# Step 1: Generate HTML with Python
python -c "
from great_tables import GT, exibble
GT(exibble).save('table.html')
"

# Step 2: Convert to element-bounded PDF
nokap from-html table.html table.pdf -s "table" -e 10
```

## Output and Exit Codes

On success, both [webshot](../reference/webshot.md#nokap.webshot) and `from-html` print the absolute path to the output file on stdout and exit with code `0`. This makes them easy to compose with other shell tools:

``` bash
$ nokap webshot https://example.com /tmp/shot.png
/tmp/shot.png
```

You can pipe the output path to another command:

``` bash
open "$(nokap webshot page.html screenshot.png)"
```

On error, a descriptive message is printed to stderr and the exit code is `1`:

``` bash
$ nokap webshot page.html out.png -s "#missing"
Error: No element matches selector: '#missing'
```

Common errors include missing selectors ([SelectorError](../reference/SelectorError.md#nokap.SelectorError)), navigation failures ([NavigationError](../reference/NavigationError.md#nokap.NavigationError)), and Chrome not being found ([ChromeNotFoundError](../reference/ChromeNotFoundError.md#nokap.ChromeNotFoundError)). See the [Error Handling](error-handling.md) guide for the full taxonomy.

## Global Options

``` bash
nokap --version   # Show version
nokap --help      # Show top-level help
nokap webshot --help  # Command-specific help
```

Every command supports `--help` for its own usage details.

## `nokap doctor`

The `doctor` command runs a full end-to-end diagnostic of your nokap installation. While `nokap info` only checks whether Chrome can be *found*, `doctor` goes further: it actually launches headless Chrome, opens a tab, renders test content, and produces both a raster screenshot and an element-bounded PDF. Each step is timed, making it invaluable for diagnosing slow environments (CI runners, Docker containers) or permission issues.

``` bash
nokap doctor
```

### What It Tests

| Step | What happens | Catches |
|----|----|----|
| 1\. Find Chrome | Locates the Chrome/Chromium binary | Missing install, bad `CHROME_PATH` |
| 2\. Launch Chrome | Starts headless Chrome, connects via WebSocket | Permission errors, port conflicts, sandboxing issues |
| 3\. Test PNG | Renders HTML and captures a PNG screenshot | Rendering failures, codec issues |
| 4\. Test PDF | Renders HTML and captures an element-bounded PDF | Print-to-PDF failures, paper sizing bugs |

### Sample Output

    nokap doctor
    ========================================
    nokap version: 0.1.0
    Python: 3.12.0
    Platform: macos (macOS-14.0-arm64)

    1. Finding Chrome... OK (0ms)
       Path: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
       Type: full browser
    2. Launching headless Chrome... OK (210ms)
       WebSocket: ws://127.0.0.1:51234/devtools/browser/abc123
    3. Test capture (HTML → PNG)... OK (320ms, 8.6 KB)
    4. Test capture (HTML → element PDF)... OK (290ms, 7.2 KB)

    All checks passed.

### When to Use

Run `doctor` when:

- **Setting up CI**: Confirm that Chrome is available and captures work before wiring up the full pipeline. If step 2 takes more than a few seconds, your container may need a warm-up step or more resources.
- **After system updates**: macOS or Linux updates can change Chrome's binary path or sandbox permissions.
- **Debugging slow captures**: The per-step timing makes it easy to tell whether the bottleneck is Chrome startup, rendering, or PDF generation.
- **First-time setup**: After installing nokap in a new environment, one `nokap doctor` confirms everything works end-to-end.

If any step fails, `doctor` prints a descriptive error message and exits with code `1`:

``` bash
$ nokap doctor
...
2. Launching headless Chrome... FAIL
   ChromeStartError: Chrome process exited immediately (exit code 1)
```

If `NOKAP_CHROME_ARGS` is set, step 1 shows its value. When a launch fails inside a sandbox, the error includes a hint about what was blocked. If the browser is full Chrome, `doctor` also suggests trying `chrome-headless-shell` (see `nokap install-chrome` below).

## `nokap install-chrome`

The `install-chrome` command downloads `chrome-headless-shell`, Chrome's standalone headless build, from [Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/) into nokap's cache directory. Once installed, nokap uses it ahead of any system Chrome (`CHROME_PATH` still takes precedence). It starts faster than full Chrome and works in macOS agent sandboxes where full Chrome can't start. nokap never downloads a browser unless you run this command.

``` bash
nokap install-chrome                          # latest stable
nokap install-chrome --version beta           # a channel: stable, beta, dev, canary
nokap install-chrome --version 156            # latest release of a milestone
nokap install-chrome --version 156.0.8078.80  # an exact version
nokap install-chrome --force                  # reinstall
```

| Option      | Default  | Description                                       |
|-------------|----------|---------------------------------------------------|
| `--version` | `stable` | Channel, milestone, or exact version              |
| `--force`   | off      | Reinstall even if this version is already present |

Running it again for a version that's already installed does nothing. Set `NOKAP_CACHE_DIR` to change where browsers are stored. The same function is available from Python as [nokap.install_chrome()](../reference/install_chrome.md#nokap.install_chrome).

## `nokap batch`

The `batch` command processes multiple capture jobs from a single JSON manifest file. Chrome is launched once and kept alive across all jobs, so you only pay the startup cost once (making this significantly faster than running individual `nokap webshot` commands in a loop). This is ideal for documentation builds, automated report generation, or any workflow where you need to capture many pages with potentially different settings.

``` bash
nokap batch [OPTIONS] MANIFEST
```

### Arguments

| Argument   | Description                                       | Default      |
|------------|---------------------------------------------------|--------------|
| `MANIFEST` | Path to a JSON file with an array of capture jobs | *(required)* |

### Options

| Option         | Short | Description                          | Default  |
|----------------|-------|--------------------------------------|----------|
| `--output-dir` | `-o`  | Directory to write output files      | `.`      |
| `--delay`      | `-d`  | Default delay for all jobs (seconds) | `0.2`    |
| `--zoom`       | `-z`  | Default zoom factor for all jobs     | `1.0`    |
| `--selector`   | `-s`  | Default CSS selector for all jobs    | *(none)* |
| `--expand`     | `-e`  | Default expand for all jobs (pixels) | `0`      |

Command-line options set *defaults* for all jobs. Individual jobs in the manifest can override any default by specifying the same key. This lets you set baseline settings once and override per-job where needed.

### Manifest Format

The manifest is a JSON array where each object describes one capture job. Every job must have:

- `"file"`: output filename (relative to `--output-dir`)
- `"url"` or `"html"`: the source to capture

All other keys are optional and map directly to [webshot()](../reference/webshot.md#nokap.webshot) / [from_html()](../reference/from_html.md#nokap.from_html) parameters:

``` json
[
  {"url": "https://example.com", "file": "homepage.png"},
  {"url": "https://example.com/pricing", "file": "pricing.png", "selector": "#plans"},
  {"url": "report.html", "file": "report.pdf", "selector": "table", "expand": 10},
  {"html": "<h1>Generated Title</h1>", "file": "title.png", "zoom": 2},
  {"url": "dashboard.html", "file": "dash.pdf", "landscape": true, "print_background": true}
]
```

Available job keys: `url`, `html`, `file`, `selector`, `expand`, `zoom`, `delay`, `vwidth`, `vheight`, `page_size`, `landscape`, `print_background`.

### Examples

Process a manifest and write all output to a directory:

``` bash
nokap batch captures.json -o output/
```

Apply a default selector and zoom to every job (individual jobs can still override):

``` bash
nokap batch tables.json -o images/ -s "table" -z 2 -e 5
```

Zero delay for static HTML files where no lazy-loading or animations occur (speeds up batch processing):

``` bash
nokap batch pages.json -o out/ -d 0
```

### Error Handling

Jobs that fail don't stop the batch. Each failure is reported inline and a summary is printed at the end:

      [1/4] https://example.com → output/example.png ... OK
      [2/4] https://bad-host.invalid → output/bad.png ... FAIL
           NavigationError: net::ERR_NAME_NOT_RESOLVED
      [3/4] report.html → output/report.pdf ... OK
      [4/4] (html string) → output/title.png ... OK

    Done: 3/4 succeeded, 1 failed.

The exit code is `1` if any job fails, `0` if all succeed. This makes it easy to use in CI: the pipeline will flag partial failures without aborting mid-batch.

### Real-World Example: Documentation Build

A documentation project might maintain a manifest of all screenshots that need regenerating:

``` json
[
  {"html": "gt_summary.html", "file": "summary_table.pdf", "selector": "table", "expand": 8},
  {"html": "gt_revenue.html", "file": "revenue_table.pdf", "selector": "table", "expand": 8},
  {"url": "http://localhost:4321/charts", "file": "chart_overview.png", "selector": "#main", "zoom": 2},
  {"url": "http://localhost:4321/dashboard", "file": "dashboard.png", "vwidth": 1440, "delay": 1.0}
]
```

Then in a Makefile:

``` makefile
screenshots:
    nokap batch docs/captures.json -o docs/images/ -d 0.5
```

This regenerates all documentation screenshots in one pass, with Chrome staying warm across all four captures.

## Next Steps

The CLI gives you access to all of nokap's capture capabilities without writing Python (useful for shell scripts, CI pipelines, Makefiles, and quick one-off captures from the terminal). Every option available in the Python API has a corresponding command-line flag.

- [Integration with Great Tables](great-tables-integration.md): Automate table screenshots
- [Error Handling](error-handling.md): Handle errors gracefully

If you're building automation around nokap, the error handling guide will help you write robust scripts that recover gracefully from common failure modes like missing selectors or Chrome startup issues.
