# overcast — verb reference

Generated from the verb registry (`overcast commands --json`). Drive any verb
from a shell via `overcast <verb> [args] --json` and parse the emitted records:
stdout is JSONL — one compact JSON record per line — and a verb can emit MORE
than one record per run (a match that clears a findings threshold appends a
suggested-finding record after the verb's own), so parse line-by-line and pick
the record whose `verb` is the one you ran; never whole-buffer `JSON.parse`.
Every verb emits one or more loose records persisted to the case's `.overcast/`
store; cite findings by `record.id` + `media.at`.

## Senses

### `overcast watch`

Runs the bound sense provider (default: tinycloud, exec) over a video file or URL and emits a video.analysis record with markdown content, a transcript (when speech is present), and the full structured describe in `detailed`. `--segment` picks the provider's segmentation — shots (shot-detected boundaries; tune with --shot-min-seconds/--shot-max-seconds) | chapters | segments | uniform:<seconds> — instead of the provider default (uniform:20). The record's meta.segmentation reports the segmentation that ACTUALLY ran — trust it over any segmentation echo inside `detailed` (tinycloud ≤ 0.3.15 echoes uniform:20 there even on a shots run); a kind mismatch with the request adds payload.warning. Footage with no hard cuts (a locked-off talk camera) legitimately yields max-duration-capped shots that LOOK uniform.

```
overcast watch <input> [options]

  Analyze a video into a reusable, time-anchored record (content/transcript/detailed).

Arguments:
  input            Video file path or URL

Options:
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
  --segment <string>     Segmentation kind passed to the provider: shots | chapters | segments | uniform:<seconds> (default: the provider's own, uniform:20)
  --shot-min-seconds <number> Min shot duration in seconds with --segment shots (e.g. 0.6 catches flash frames)
  --shot-max-seconds <number> Max shot duration in seconds with --segment shots
```

Emits `video.analysis` records.

### `overcast listen`

Default provider: tinycloud. Speech-only transcript by default; --describe runs the full multimodal describe to surface the AUDIO-SCENE description (sounds, music, events, ambience), not just speech. Emits transcript, speaker-tagged segments[] with media.at anchors, language.

```
overcast listen <input> [options]

  Transcribe and analyze audio (or a video's audio track) into an audio.analysis record.

Arguments:
  input            Audio/video file path or URL

Options:
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
  --describe             Audio-scene description (full describe), not just speech
  --diarize              Attribute speech to distinct speakers
  --lang <string>        Hint/force source language (e.g. en, es)
```

Emits `audio.analysis` records.

### `overcast see`

Defaults to the BRAIN LLM when it supports images: a direct 'describe this image in detail' call (turnkey with the Cloudglue brain, or any image-capable `setup llm`). Falls back to a Hugging Face captioner when HF_TOKEN is set (override with HF_SEE_MODEL), else a placeholder until a VLM is bound. Switch backends via `setup provider see builtin:hf` (classic HF) or `builtin:brain`; disable the brain default with OVERCAST_SEE_BRAIN=off. Forwards --ocr/--prompt; --detect needs a detection provider (OWLv2 for boxes, or the opt-in Cloudglue tinycloud see/extract provider for boxless facts, tinycloud >= 0.3.7). Accepts frame://rec@sec (resolved via the internal ffmpeg toolkit) and http(s) image URLs, fetched into the case media dir first (meta.source_url keeps the origin).

```
overcast see <input> [options]

  Understand an image or a single video frame (caption, OCR, detections).

Arguments:
  input            Image path, http(s) image URL, video frame, or frame://rec@sec

Options:
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
  --ocr                  Extract on-image text
  --detect <string>      Comma list of target objects to locate (bind the detect provider for bounding boxes)
  --prompt <string>      Focus the description
```

Emits `image.analysis` records.

### `overcast face`

Default provider: tinycloud. `face <video>` detects faces — one box per sampled frame, so the count is detections, NOT unique people (detect doesn't cluster). To find or count a PERSON, use `face <video> --match ref.jpg` (locates that person in the clip, ranked by similarity), or `face --match ref.jpg --index <id>` to search a registered face-analysis index (case-wide); `face <video> --index <id>` lists that video's stored detections. The video/reference may be a path, URL, or a case record id; the reference image for --match must be JPEG/PNG. Emits a face.analysis record whose `summary` is the headline, plus faces[] (at, box, similarity, thumbnail?) and the full provider data in `detailed`.

```
overcast face [input] [options]

  Detect, match, or search faces in video (and across face-analysis indexes).

Arguments:
  input            Video to analyze (path/URL/record-id); omit with --match + --index to search the index

Options:
  --match <string>       Reference face image to find (JPEG/PNG path/URL/record-id)
  --index <string>       Face-analysis index id/name to search or list within (comma-list ok; default: the case's face index)
  --max-faces <number>   match: cap returned matches (1–4000)
  --min-similarity <number> match/search: similarity floor (0–100)
  --thumbnails           detect/match: include per-face thumbnail URLs
  --fps <number>         detect/match: sampling frames per second; local face accepts --max-frames as a cap
  --max-frames <number>  local face: video frame sample count/cap
  --start <string>       detect/match: window start (SS or timecode)
  --end <string>         detect/match: window end (SS or timecode)
  --limit <number>       detect/list/search: max results (match uses --max-faces)
  --offset <number>      list/search: result offset
  --group-by <string>    search: group results by file
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `face.analysis` records.

### `overcast image`

`image add <image|record-id> --index <local-image-index>` stores a reference image in a local image-ransac index. `image match <image|video|record-id> --index <local-image-index>` searches that DB using OpenCV SIFT/ORB + RANSAC.

```
overcast image <action> [input] [options]

  Match images or video frames against a local RANSAC image index.

Arguments:
  action           add | match
  input            image/video path, URL, or record id

Options:
  --index <string>       local image-ransac index id/name
  --to <string>          alias for --index when adding
  --min-inliers <number> minimum RANSAC inliers
  --min-ratio <number>   minimum inlier ratio
  --ratio-test <number>  Lowe ratio-test threshold
  --fps <number>         video frame sampling rate; --max-frames can cap it
  --max-frames <number>  video frame sample count/cap
  --draw                 write match visualization images
  --format <string>      json | md | txt
  --json                 Shorthand for --format json
```

Emits `image.match` records.

### `overcast audio`

`audio add <audio|video|record-id> --index <local-audio-fp-index>` fingerprints a recording (Wang 2003 constellation hashes) and caches it in a local audio-fp index. `audio match <query> --index <id>` finds which indexed recording contains the query and WHERE (offset-histogram alignment: 'query audio appears at 01:23 in recording Y'). `audio match <query> <reference>` compares two clips directly, no index needed. Videos are accepted — their audio track is extracted. Robust to transcode/noise/clipping; NOT robust to pitch/speed change.

```
overcast audio <action> [input] [reference] [options]

  Shazam-style exact audio matching: fingerprint clips into a local audio-fp index, or match clip-to-clip with time-offset alignment.

Arguments:
  action           add | match
  input            audio/video path, URL, or record id (the query for match)
  reference        match: a second clip for direct clip-to-clip comparison (instead of --index)

Options:
  --index <string>       local audio-fp index id/name
  --to <string>          alias for --index when adding
  --min-votes <number>   minimum time-aligned hash votes to confirm a match (default: 6)
  --min-ratio <number>   minimum aligned-votes / query-hashes ratio (0–1)
  --min-margin <number>  minimum ratio of best-offset votes over the next-best offset (≥1); a true exact match scores 100s–1000s×, a pitch/speed-shifted copy ~1.2–1.7× — raise this (e.g. 2) to reject sped-up re-uploads
  --draw                 match: render an SVG alignment visualization per match (hash-pair scatter + offset histogram) — embeds in briefs like image --draw
  --format <string>      json | md | txt
  --json                 Shorthand for --format json
```

Emits `audio.match` records.

### `overcast voice`

`voice add <audio|video|record-id> --index <local-voice-print-index>` embeds a clip's voiced windows (pyannote wespeaker speaker embeddings, run locally) and caches them in a local voice-print index. `voice match <clip> <sample>` ranks where the sample's SPEAKER talks in the clip (windowed cosine scan; `--diarize` upgrades to diarize-then-match against per-speaker centroids — needs HF_TOKEN + the accepted pyannote license like `enhance --ops separate`, and falls back to windowed without it). `voice match <sample> --index <id>` ranks which enrolled members contain the speaker. Videos are accepted — their audio track is extracted. `similarity` is a 0–100 rank score (anchored cosine; 50 ≈ the accept floor, 90 ≈ strong same-speaker), not a probability, and NOT liveness — a cloned/synthetic voice can score high; cross-language or degraded speech scores lower. To list a clip's speakers without a reference, use `enhance --ops separate`.

```
overcast voice <action> [input] [sample] [options]

  Speaker verification: enroll voices into a local voice-print index, or find/rank a reference voice inside a clip or across members.

Arguments:
  action           add | match
  input            audio/video path or record id (add: the clip to enroll; match: the clip to scan, or the sample when searching --index)
  sample           match: the reference voice sample for pairwise `voice match <clip> <sample>` (instead of --index)

Options:
  --index <string>       local voice-print index id/name
  --to <string>          alias for --index when adding
  --min-similarity <number> score floor 0–100 (default 50 ≈ the accept threshold; suggested findings fire at 80)
  --min-margin <number>  minimum score-point gap between the best match and the runner-up speaker (diarized) or the clip's median window (windowed/search) — a cheap calibration gate
  --diarize              pairwise match: diarize-then-match (overlap-aware; needs HF_TOKEN + accepted pyannote license, else falls back to windowed)
  --speakers <number>    match --diarize: expected speaker count hint
  --start <string>       pairwise match: scan window start (seconds or HH:MM:SS)
  --end <string>         pairwise match: scan window end (seconds or HH:MM:SS)
  --window <number>      pairwise match: seconds per embedding window (default 3; members follow the index config)
  --limit <number>       match: max results
  --offset <number>      match --index: result offset
  --format <string>      json | md | txt
  --json                 Shorthand for --format json
```

Emits `voice.match` records.

### `overcast cluster`

A persistent LOCAL face database backed by the deepface provider (clustering needs face embeddings, which the tinycloud face path doesn't expose). `cluster add <media>` detects faces, embeds them, and ASSIGN-OR-CREATEs each into a person (nearest existing person above --min-similarity, else a new one); `cluster identify <image|video>` surfaces the most similar person for a probe (or flags it as a likely new person) without writing; `cluster recluster` re-groups every stored face and carries human labels forward; `cluster list`/`show` read the DB and `cluster view` renders a self-contained HTML contact sheet. Needs a face-cluster index (`index create <name> --type face-cluster --local`); resolves the case's sole one when --index is omitted. Emits a `cluster` record.

```
overcast cluster <action> [arg] [arg2] [options]

  Build and browse a local face-cluster DB: group faces into people, identify, label, and view.

Arguments:
  action           add | ingest | identify | list | show | label | recluster | view
  arg              add/identify: media (path/URL/record-id) · show/label: person id
  arg2             label: the name to assign (cluster label <person-id> <name>)

Options:
  --index <string>       face-cluster index id/name (default: the case's sole face-cluster index)
  --min-similarity <number> add/identify: assign-or-create threshold; recluster: linkage threshold (0–100)
  --cluster <string>     show/label: the person id (alternative to the positional)
  --label <string>       label: the name to assign (alternative to the positional)
  --fps <number>         add/identify: sampling frames per second (video)
  --max-frames <number>  add/identify: video frame sample count/cap
  --start <string>       add/identify: window start (SS or timecode)
  --end <string>         add/identify: window end (SS or timecode)
  --limit <number>       list/show/identify: max results
  --source-record <string> add: the case record id the media came from
  --out <string>         view: HTML output path (default: .overcast/media/cluster-<id>.html)
  --no-open              view: write the gallery but don't launch it
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `cluster` records.

### `overcast similar`

`similar add <image|video> --index <basic-clip-index>` embeds and caches a reference in a local CLIP DB (videos are frame-sampled and pooled); a `basic-clap` index instead embeds audio (or a video's audio track) with CLAP. `similar match <image|video|audio> --index <id>` ranks members by image→image (CLIP) or audio→audio (CLAP) similarity; `similar search "<text>" --index <id>` ranks members by text→image (CLIP) or text→audio (CLAP) similarity. Runs OpenAI CLIP / LAION CLAP locally; scores are cosine×100 (0–100).

```
overcast similar <action> [input]... [options]

  Find images/video moments or audio by visual, audio, or text similarity in a local CLIP (basic-clip) or CLAP (basic-clap) index.

Arguments:
  action           add | match | search
  input            image/video/audio path, URL, record id (add/match) — or a text query (search)

Options:
  --index <string>       local basic-clip (CLIP) or basic-clap (CLAP audio) index id/name
  --to <string>          alias for --index when adding
  --min-similarity <number> match/search: similarity floor (0–100)
  --limit <number>       match/search: max results
  --offset <number>      match/search: result offset
  --pooling <string>     match: pool the query's frames/windows by max | mean (members follow the index config)
  --granularity <string> video (one vector per file) | frame (moments — video frames, or 10s audio windows for basic-clap) — set at `index create`; members always follow the index config
  --sampling <string>    basic-clip only — match query video: uniform windows | shots (tinycloud watch boundaries); members follow the index config
  --window <number>      seconds per uniform sampling window (basic-clip video) or audio chunk (basic-clap)
  --fps <number>         video: frame sampling rate; --max-frames can cap it
  --max-frames <number>  video: frame sample count/cap
  --format <string>      json | md | txt
  --json                 Shorthand for --format json
```

Emits `similar.match` records.

### `overcast exif`

Runs ExifTool over an image or video and emits a media.metadata record: a searchable summary plus GPS coordinates (signed decimals), capture time, camera make/model/serial/lens (the device-linking fingerprint `devices` groups by), editing software, MIME/dimensions/duration, and a total tag count. The default backend is the shipped ExifTool provider (system `exiftool` on PATH; install with `brew install exiftool` / `apt install libimage-exiftool-perl`); bind your own with `setup provider exif <spec>`. Accepts a path, a case record/capture id, or an http(s) URL (fetched into the case media dir first). The full raw tag dump stays in-provider — only the compact summary is indexed. Pass `--geocode` to reverse-geocode the GPS into a place name via a bound (opt-in) `geocode` provider.

```
overcast exif <input> [options]

  Extract embedded metadata — GPS, capture time, device — from an image or video (ExifTool).

Arguments:
  input            Image/video/file path, case record id, or http(s) URL

Options:
  --geocode              Reverse-geocode GPS to a place via a bound `geocode` provider (opt-in — sends coordinates to that provider)
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `media.metadata` records.

### `overcast verify`

Reads the embedded C2PA / Content Credentials manifest of an image or video and emits a media.provenance record: whether a signed manifest is present, the claim generator, the signer/certificate issuer, the signature algorithm, the validation state + codes, and assertion/ingredient counts. Media with no credentials is a clean `ready` record (`has_manifest: false`), not an error. The default backend is the shipped c2patool provider (system `c2patool` on PATH; install with `brew install c2patool`); bind your own with `setup provider verify <spec>`. Accepts a path, a case record/capture id, or an http(s) URL. Distinct from source-post provenance (where a record came from) — this checks the media's own embedded credentials.

```
overcast verify <input> [options]

  Check a media file's C2PA / Content Credentials provenance manifest (c2patool).

Arguments:
  input            Image/video/file path, case record id, or http(s) URL

Options:
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `media.provenance` records.

### `overcast screenshot`

Captures what a page LOOKS like — the rendered state, not the raw HTML a plain capture fetches. Default backend: the shipped Playwright engine (install with `npm install --include=optional` + `npx playwright install chromium`; missing deps yield a needs_credentials record, and `overcast doctor` checks the renderer). Also accepts a local .html file — render a wall/map/brief export into image evidence. The PNG lands in the case media dir; chain it into `see` (describe/OCR), `exif`, `note --ref`, or `archive add`. For watching a page over time, register the same engine as a source: `source add browser:<url>` + `monitor --pull`. Private/loopback targets are refused by default (OVERCAST_ALLOW_PRIVATE_FETCH=1 to allow). Treat rendered pages as untrusted content (prompt-injection surface) — a capture may also show a bot-challenge or login wall; that rendered state is still the evidence. Element (--selector) and video capture are not yet supported.

```
overcast screenshot <url> [options]

  Render a web page (or local HTML export) to a PNG evidence record via headless Chromium.

Arguments:
  url              Page URL (http/https) or local .html path

Options:
  --full-page            Capture the full scrollable page, not just the viewport
  --viewport <string>    Viewport size as WxH (default 1280x800)
  --wait <number>        Extra settle time in ms after load (capped at 15s)
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `web.screenshot` records.

### `overcast enhance`

Default: deterministic, modality-dispatched ops on the bundled ffmpeg (denoise/normalize/voice-isolate/upscale/stabilize/grayscale). Bind a model/analysis provider for AI restoration or the PROVIDER-ONLY ops via `setup provider enhance <spec>`: `--ops separate` splits an audio/video's voices into per-speaker tracks (add --summarize to transcribe each), `--ops segment --prompt "<thing>"` cuts requested objects out of an image as mask + cutout evidence, `--ops ela` derives ELA/noise/luminance forensic overlays from an image (heuristic edit-detection leads), `--ops panorama` stitches a panning video into one wide still (skyline/landmark exposure for geolocation). These ops need a bound provider (local-models = pyannote + GroundingDINO/SAM2, fal = sam-audio + sam-3, or the shipped ela/panorama catalog choices); image segmentation/ela of a video is out of scope (run on a frame:// still). Emits a media.enhanced record per output — for the fan-out ops, one child record per track/mask/overlay whose media.ref chains into watch/listen/see/view/crop.

```
overcast enhance <input> [options]

  Produce better media (denoise/normalize/upscale), split it (separate voices / segment objects), or derive analysis artifacts (ela forensic overlays / panorama stitch) via ffmpeg or a bound provider.

Arguments:
  input            Media file path

Options:
  --ops <string>         Comma list of ops (denoise,normalize,upscale,separate,segment,ela,panorama,...)
  --prompt <string>      What to segment (--ops segment) or the target voice to extract
  --speakers <string>    Speaker-count hint for --ops separate
  --summarize            Transcribe/summarize each separated track via the bound listen provider
  --masks-only           For --ops segment, emit binary masks instead of RGBA cutouts
  --out <string>         Output path (default .overcast/media/)
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `media.enhanced` records.

### `overcast reconstruct`

Scene reconstruction: hold the camera at a captured moment, then move it. Give an image (or a video + --at to pick the frame) and either camera moves — `--rotate <deg>` (0 front / 90 right / 180 behind, negative = left) with optional `--elevate <-30..90>` and `--zoom <0..10>` — or an op: `--ops sweep` synthesizes --count camera stops around 360° and assembles a labeled contact sheet + turntable video, `--ops model` lifts a textured 3D mesh (GLB) you can orbit in the built-in viewer, `--ops depth` estimates a depth map rendered as a drag-to-parallax hologram, `--ops age` is the sketch artist: age (+N) or de-age (-N) the SUBJECT OF A REAL PHOTO by `--age-years <±years>` (-40..+60; missing-person age progression). The aged image is a speculative synthesized LIKENESS — NEVER use it as a probe for face/cluster/similar matching or to identify anyone; composing a face from a text description (no real photo to anchor to) is deliberately unsupported. Every output is GENERATIVE — synthesized pixels stamped with payload.caveat, excluded from ask/brief evidence and findings triggers; use it to form hypotheses (what's around the corner? what would a second camera have seen? what might they look like today?), then verify with real captures. Needs a bound provider (no built-in): `overcast provider setup apply --verb reconstruct --choice fal --yes` (FAL_KEY). `view <record-id>` reopens the gallery / 3D orbit / parallax viewer; --view opens it immediately.

```
overcast reconstruct <input> [options]

  Speculatively reposition the camera in a still (rotate/elevate/zoom, turntable sweep, 3D model, depth) or age-progress the subject of a real photo (--ops age) via a bound generative provider — a hypothesis renderer, never evidence.

Arguments:
  input            Image (or video with --at) — path, record id, frame://rec@sec, or archive:<bucket>/<item>

Options:
  --rotate <number>      Camera azimuth in degrees (0 front, 90 right, 180 behind; negative = left)
  --elevate <number>     Camera elevation in degrees (-30 low-angle … 0 eye-level … 60 high … 90 bird's-eye)
  --zoom <number>        Camera distance 0-10 (0 wide, 5 as-shot, 10 close-up)
  --ops <string>         Reconstruction op: view (default with --rotate) | sweep | model | depth | age (default with --age-years)
  --count <number>       Sweep: number of synthesized camera stops around 360° (2-24, default 8)
  --age-years <number>   Age op: years to age (+N) or de-age (-N) the subject (-40..+60) — output is a synthesized likeness, never a face-match probe
  --at <string>          Video input: timestamp (SS or MM:SS) of the frame to reconstruct from
  --prompt <string>      Extra scene hint forwarded to the view-synthesis model
  --seed <number>        Generation seed for reproducibility
  --view                 Open the reconstruction viewer (gallery / 3D orbit / parallax) when done
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `media.reconstruction` records.

### `overcast chronolocate`

Pure offline solar-position math (no API/key). VERIFY mode (--at-time <ISO>): given a location and a claimed capture time, computes the sun's azimuth/altitude and the shadow it must cast, so you can check it against the frame (a mismatch flags a mis-dated or staged image). SOLVE mode (--shadow-azimuth <deg>): given a location and an OBSERVED shadow bearing (0=N,90=E,180=S,270=W), returns the time window(s) on a date (--date, default today) when the sun would cast it; add --height-ratio <object:shadow> to also use shadow LENGTH and narrow the window. Location comes from --lat/--lng or, when the positional input is a case record carrying payload.gps (e.g. an `exif` hit), from that record. The result carries payload.gps (plots on `map`) and payload.caveat — chronolocation is a lead, not proof (a clone/edit can fake shadows).

```
overcast chronolocate [input] [options]

  Chronolocation from the sun/shadows: solve WHEN a photo was taken, or verify a claimed time.

Arguments:
  input            Optional: a case record id (pulls its GPS + links its media) or an image/frame ref

Options:
  --lat <number>         Latitude (WGS84) — overrides a record's GPS
  --lng <number>         Longitude (WGS84) — overrides a record's GPS
  --at-time <string>     VERIFY: claimed capture time (ISO 8601; bare datetime read as UTC)
  --shadow-azimuth <number> SOLVE: observed shadow bearing in degrees from North (0=N,90=E,180=S,270=W)
  --height-ratio <number> SOLVE: object-height ÷ shadow-length, to also constrain by shadow length
  --date <string>        SOLVE: reference date YYYY-MM-DD (declination varies by date); default today
  --az-tol <number>      SOLVE: azimuth match tolerance in degrees (default 3) (default: 3)
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `chrono.estimate` records.

## Inspect

### `overcast view`

For video/audio, generates a self-contained HTML player (timeline + markers for a referenced record's media.at) and opens it. For other files, uses the OS open command. Given an `enhance` split-op PARENT record (--ops separate/segment), renders a GALLERY of its fanned-out children instead — per-speaker audio players + spectrograms for separate (with cross-talk regions), or cutout/mask images for segment. Given a `reconstruct` record, renders its dedicated viewer: a speculative gallery (view/sweep), an embedded 3D orbit viewer (model / mesh children), or a drag-parallax hologram (depth). --no-open writes the viewer and emits a view record with its path.

```
overcast view <ref> [options]

  Open media in a lightweight local viewer (scrubbable player) or hand off to the OS.

Arguments:
  ref              Media path, capture-id, or record-id

Options:
  --at <string>          Start at SS or seek a START-END span
  --spectrogram          (audio) also render a spectrogram
  --no-open              Write the viewer but don't launch it
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `view` records.

### `overcast crop`

Takes a face or see detection record and writes cropped still images under .overcast/media/crops/. For detections with frame thumbnails, crop uses the supplied frame image as the crop source. Each crop record preserves the source record, source media, crop source media, timestamp/frame, class/id, confidence, and box. Use --all, --id, --class, or --kind to select detections; crops are memory-friendly evidence artifacts.

```
overcast crop <input> [options]

  Materialize face/object detections as cropped image records with provenance.

Arguments:
  input            Detection record id (face/see)

Options:
  --all                  Crop every matching detection
  --id <string>          Crop one detection/face/track id
  --class <string>       Filter by class/label, e.g. face, person, car
  --kind <string>        Filter detection kind: face | object
  --pad <number>         Expand the crop box by a fraction, e.g. 0.15
  --square               Make the crop square around the detection box
  --limit <number>       Maximum crops to write
  --out <string>         Output directory (default .overcast/media/crops)
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `media.crop` records.

### `overcast grid`

Samples frames from a video — uniformly across a --start/--end window (default the whole clip, --count frames) or at an explicit --at timestamp list — and tiles them into ONE contact-sheet image via the internal ffmpeg toolkit, burning each cell's number + timestamp when the ffmpeg build has drawtext (else the sheet is unlabeled and cells are numbered left-to-right, top-to-bottom). Emits a media.grid record whose media.ref is the montage and whose payload.cells maps cell number → exact timestamp. Chain it: `overcast see <montage-path> --prompt "which numbered cell best shows X? give the cell number"` then read payload.cells to recover the source time — one VLM call triages a long clip before a frame-precise zoom-in (see frame://<record>@<sec>). Add --view for a clickable HTML contact sheet (cells labeled with their timestamp even when ffmpeg can't burn labels, each seeking the source video on click); --no-open writes it without launching.

```
overcast grid <input> [options]

  Tile timestamped video frames into a labeled contact sheet for one-shot VLM triage.

Arguments:
  input            Video file path or case record id

Options:
  --count <number>       Number of frames to sample across the window (default 16)
  --at <string>          Explicit comma list of timestamps (SS or MM:SS), overrides --count/window
  --start <string>       Window start (SS or MM:SS)
  --end <string>         Window end (SS or MM:SS)
  --cols <number>        Grid columns (default ceil(sqrt(count)), max 12)
  --width <number>       Cell width in px (default 320)
  --out <string>         Output image path (default .overcast/media/)
  --view                 Also render a clickable HTML contact sheet (numbered cells seek the source video)
  --no-open              With --view, write the HTML board but don't launch it
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `media.grid` records.

### `overcast wall`

Generates a self-contained HTML wall of muted, looping video tiles — each anchored to its best evidence moment (open finding > face hit > record anchor) — overlaid with case state: sense-coverage badges, findings, per-source scan / monitor / brief freshness. Local media is referenced by file:// URL (not embedded); missing or browser-hostile media renders a NO SIGNAL / STILL tile (with an ffmpeg poster frame when extractable). Click a tile to open the media at its anchor; hover for the intel card. --infinite repeats the real feeds to fill the screen and keeps extending the grid as it scrolls — an endless monitor bank even from a handful of feeds. --no-open writes the wall and emits a record with its path instead of launching.

```
overcast wall  [options]

  Open a control-room monitor wall: case videos looping at their evidence moments.

Options:
  --limit <number>       Max tiles, most evidentiary/recent first (~25 is a practical decode ceiling) (default: 12)
  --source <string>      Only media from this source type (youtube | tiktok | x | web | lens | local)
  --since <string>       Only media with records since (e.g. 24h, 7d, 2026-06-01)
  --export <string>      Wall HTML path (default: .overcast/media/wall.html)
  --refresh <number>     Auto-reload the wall every N seconds (restarts the feeds)
  --infinite             Endless wall: repeat feeds to fill the screen and keep extending on scroll
  --no-open              Write the wall but don't launch it
  --theme <string>       HTML theme: plain | csi (default: plain)
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `wall` records.

### `overcast situation`

`serve` (default; operator/CLI only — run it in its own terminal pane) starts a token-authenticated local server (default 127.0.0.1:7374) and opens the live console: video-wall tiles looping at their evidence moments, a reverse-chron feed of scan hits, a live map of every gps-bearing record (flights build tracks), and the freshest webcam/browser stills — panels auto-picked from your configured sources unless --panels pins them. The page refreshes itself whenever case records land (from the agent, `scan --pull`, or a separate `monitor --every`); with --every the serving process runs the monitor cadence itself, so one command IS 'monitor the situation'. Local media streams over an authenticated /media route (remote embeds stay off unless OVERCAST_REPORT_REMOTE_MEDIA=1). `status`/`set`/`stop` are the agent-safe control plane via .overcast/situation/ — `set` retunes panels/filters/theme on the fly, `stop` shuts the page down (applied within ~2s). In the TUI, /situation on runs the server in-process instead.

```
overcast situation [action] [options]

  Monitor the situation: a live web page over the case — wall + feed + map + stills, updating as records land (serve | status | set | stop).

Arguments:
  action           serve | status | set | stop (default: serve)

Options:
  --every <string>       serve: own the monitor cadence (e.g. 5m, 1h) — runs a monitor pass each interval
  --port <number>        serve: listen port (default 7374; 0 = ephemeral)
  --bind <string>        serve: bind address (default 127.0.0.1 — keep it off public ifaces)
  --panels <string>      Panels to show: comma list of wall,feed,map,stills — or 'auto' (default: auto from sources)
  --source <string>      Only content from these source ids/types (comma list)
  --since <string>       Only content since (e.g. 24h, 7d, 2026-06-01)
  --limit <number>       Max wall tiles (default 12; other panels have fixed caps)
  --theme <string>       Console theme: csi | plain (default: csi)
  --query <string>       Ad-hoc monitor query (used by the --every cadence)
  --clear <string>       set: drop filters back to default/auto (comma list of panels,source,since,limit,theme,query)
  --poll <number>        serve: data-refresh cadence seconds (default 60; control stays ~2s; ⟳/monitor passes force now)
  --no-open              serve: don't launch the browser
  --force                stop: also SIGTERM the serving pid (when control isn't picked up)
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `situation` records.

### `overcast map`

Gathers all case records with payload.gps{lat,lng} (primarily `exif`; any record qualifies) and renders a self-contained HTML map — one marker per point with its record id, media thumbnail, geocoded place (when `exif --geocode` set it), and capture time, linking back to the source. Online mode fetches OSM raster tiles in the browser at view time (no CDN dependency; the map JS is inlined); --offline degrades to a coordinate scatter with per-point openstreetmap.org links and no network egress. --near <lat,lng> (--radius meters, default 500) or --bbox <minLat,minLng,maxLat,maxLng> spatially filter the plotted points — the same fence semantics as `geofence`. --no-open writes the map and emits its path instead of launching. Live tiles reveal the viewer's IP + the investigated location to OpenStreetMap.

```
overcast map  [options]

  Plot every case record carrying GPS coordinates on a self-contained HTML map.

Options:
  --limit <number>       Max points, most-recent first (default: 500)
  --since <string>       Only records since (e.g. 24h, 7d, 2026-06-01)
  --near <string>        Only points within --radius meters of 'lat,lng'
  --radius <number>      Radius in meters around --near (default 500)
  --bbox <string>        Only points inside 'minLat,minLng,maxLat,maxLng' (inclusive, non-wrapping)
  --offline              No tile fetch: coordinate scatter + openstreetmap.org links only
  --export <string>      Map HTML path (default: .overcast/media/map.html)
  --no-open              Write the map but don't launch it
  --theme <string>       HTML theme: plain | csi (default: plain)
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `media.map` records.

### `overcast geofence`

The geofence query: gathers all case records carrying payload.gps{lat,lng} (`exif`, and geo sources like dispatch/firms/flights/overpass) and returns the ones intersecting a location fence — a --near <lat,lng> circle (--radius meters, default 500) or a --bbox <minLat,minLng,maxLat,maxLng> box (inclusive edges, non-wrapping) — captured within [--since, --until]. Recency uses the CAPTURE time (exif payload.created) when present, falling back to ingest time; undated records that intersect spatially are KEPT (they can't be excluded by time — the map/wall convention) with capture_time null. Pure local read, no network. Emits ONE operational rollup record (matches newest-first, per-verb counts, the query echoed back) — a viewer over evidence, never ask/brief evidence itself. An empty intersection is a clean ready record with guidance, not an error.

```
overcast geofence  [options]

  List every case record whose GPS falls inside a radius/box within a time window.

Options:
  --near <string>        Fence center 'lat,lng' (circle mode; pairs with --radius)
  --radius <number>      Circle radius in meters around --near (default 500)
  --bbox <string>        Fence box 'minLat,minLng,maxLat,maxLng' (inclusive, non-wrapping)
  --since <string>       Window start (e.g. 24h, 7d, 2026-06-01) — capture-time-aware
  --until <string>       Window end (same grammar as --since)
  --limit <number>       Max matches returned, most-recent first (default: 500)
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `geofence.result` records.

### `overcast devices`

Rolls up all case `exif` records into device clusters keyed by make + model + serial + lens. A serial number is a durable per-device id (a strong link — same serial ≈ same physical camera); when a serial is absent the cluster falls back to make + model + lens (a weaker 'same model' hint). Reports every cluster of ≥2 media shot on the same device — e.g. an anonymous account's photo sharing a camera serial with an identified one. Pure read over records already in memory (no new index; run `exif` on media first so serial/lens are populated). With --findings it also emits `suggested` findings for serial-linked (strong) clusters, deduped by fingerprint.

```
overcast devices  [options]

  Correlate case media by camera fingerprint (make/model/serial/lens) and report shared-device clusters.

Options:
  --min <number>         Minimum media per cluster to report (default: 2)
  --findings             Also emit suggested findings for serial-linked (strong) clusters
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `devices` records.

### `overcast graph`

Connects the dots across the case: evidence records (the same ask/brief evidence boundary), shared media, targets (lines of investigation), accepted/open findings, cluster people, camera-fingerprint devices, places (payload.place / GPS), and typed entities harvested by conservative regex from evidence text (email, phone, @handle, url/domain, hashtag) plus structured lifts (exif serial, scan handles/identity fields). Edges carry provenance record ids: record↔media, finding→source/target, note→record, match-verb links (face/image/audio/voice/similar), device membership, entity mentions, and the shared target↔evidence thread matcher. --extract additionally runs the configured brain LLM (BYO, text-only) over evidence text for entity/relation extraction — results cache to .overcast/graph/extract.jsonl (delete the file to re-extract) and are marked as leads, not proof. --focus restricts to the 2-hop neighborhood of a node/record/entity; --limit trims lowest-degree leaf entities first (never records with findings). The viewer is fully offline: inlined hand-rolled canvas force layout, pan/zoom, per-type toggles, text filter, and a node inspector with `overcast view` / `case memory get` command hints.

```
overcast graph  [options]

  Build the case knowledge graph and render it as a self-contained interactive HTML viewer.

Options:
  --extract              Also run the brain LLM over evidence text for entity/relation extraction (cached)
  --since <string>       Only evidence since (e.g. 24h, 7d, 2026-06-01)
  --limit <number>       Max nodes (lowest-degree leaf entities trim first) (default: 400)
  --focus <string>       Restrict to the 2-hop neighborhood of a node id, record id, media ref, or entity text
  --export <string>      Graph HTML path (default: .overcast/media/graph.html)
  --no-open              Write the viewer but don't launch it
  --theme <string>       HTML theme: plain | csi (default: plain)
  --format <string>      Output surface: json | md | txt
  --json                 Shorthand for --format json
```

Emits `media.graph` records.

## OSINT

### `overcast scan`

Enumerates each enabled source by its bound ref (channel/handle/hashtag/keyword); an explicit --query overrides, and the active target is the fallback when a source has no ref. With --pull, each hit uses the same media.ref/payload.url, capture, sense, and failure semantics as monitor. If the case has no enabled external sources, scan falls back to local case media/indexes and can run a face-index search when an image target and face-analysis index are available.

```
overcast scan  [options]

  Sweep sources, or local case media/indexes when no sources exist; emit scan.hit records (--pull to capture+sense).

Options:
  --query <string>       Ad-hoc keyword search across sources
  --source <string>      Restrict to source ids/types (comma list)
  --since <string>       Only items newer than e.g. 24h, 2026-06-01
  --limit <number>       Max hits per source; with --local, max local visual DB candidates
  --local                Scan local case media/indexes instead of external sources
  --pull                 Auto-capture + sense each hit
  --transcript           With --pull, yt-dlp sources: captions + metadata per hit instead of the video
  --thumb                With --pull, yt-dlp sources: thumbnail image per hit instead of the video
  --lang <string>        With --transcript: caption language (default en)
  --pipe <string>        Sense to run on pulled hits (watch|listen|face|exif|verify)
  --describe             With --pipe listen: full audio-scene describe (not speech-only)
  --format <string>      json | md | txt
  --json                 Shorthand for --format json
```

Emits `scan.hit` records.

### `overcast capture`

Acquires media/content into .overcast/media/: a local path is copied in; a URL is downloaded via the matching source provider. Emits a capture record with a capture_id usable by the senses.

```
overcast capture <ref> [options]

  Fetch a resource (URL / scan.hit / local path) into the case as a capture record.

Arguments:
  ref              URL, scan.hit id, local path, or - for stdin

Options:
  --index                Embed into the case index after capture
  --out <string>         Output location override
  --transcript           yt-dlp sources: captions + metadata instead of the video (no video download)
  --thumb                yt-dlp sources: thumbnail image instead of the video (no video download)
  --lang <string>        With --transcript: caption language (default en)
  --format <string>      json | md | txt
  --json                 Shorthand for --format json
```

Emits `capture` records.

### `overcast monitor`

Enumerates sources, diffs against .overcast/seen.json, and for each NEW item uses the shared scan --pull processor: resolve media.ref/payload.url, capture when needed, then run explicit --pipe or setup automation/default watch. Hard processing failures are surfaced and marked seen; pending/credential gaps remain retryable. --once = single diff pass (scheduler-friendly). --every <15m|6h|…> = continuous blocking loop (run under tmux; Ctrl-C to stop); each pass streams its records. --brief summarizes the new batch; --alert <stdout|file> mirrors new records to a sink.

```
overcast monitor  [options]

  scan on a loop; diff against the seen-set; pipe new items into a sense. --once or --every <interval>.

Options:
  --source <string>      Restrict to source ids/types
  --query <string>       Ad-hoc keyword search across sources
  --since <string>       Only items newer than e.g. 24h, 2026-06-01
  --limit <number>       Max hits per source
  --transcript           yt-dlp sources: captions + metadata per new item instead of the video
  --thumb                yt-dlp sources: thumbnail image per new item instead of the video
  --lang <string>        With --transcript: caption language (default en)
  --pipe <string>        Sense to run on new items (watch|listen|face|exif|verify)
  --describe             With --pipe listen: full audio-scene describe (not speech-only)
  --once                 Single diff pass then exit
  --every <string>       Continuous loop cadence (e.g. 15m, 6h)
  --brief                Summarize the new batch into a brief record
  --alert <string>       Mirror new records to a file sink (they already stream to stdout)
  --format <string>      json | md | txt
  --json                 Shorthand for --format json
```

Emits `scan.hit` records.

### `overcast index`

An index is a Cloudglue-backed searchable corpus of videos, searched one way per TYPE: media-descriptions (ask/probe), entities (same-schema extraction), face-analysis (detect + find a person). `create <name> --type <media|entities|face>` (entities needs --prompt/--schema); `attach <remote-id-or-name>` mirrors an existing remote index into this case; `add <video> --to <id>` registers a video (a path, URL, or a case record id) — `--all` registers every video the case has captured or sensed (watch/listen/face) for the target; `list`/`show <id>` inspect; `delete <id>`/`remove <video> --from <id>` prune; `entities <id> <video>` fetches a video's extracted entities. Then read with `ask --index <id>`, `face --match … --index <id>`, or `index entities`. Backed by tinycloud (≥ 0.3.4).

```
overcast index <action> [arg] [arg2] [options]

  Manage tinycloud indexes that index a target's videos (create/attach/add/list/show/delete/remove/entities).

Arguments:
  action           create | attach | add | list | show | delete | remove | entities
  arg              name (create) · remote id/name (attach) · video/record-id (add/remove) · index id (show/delete/entities)
  arg2             entities: the video/record-id (index entities <id> <video>)

Options:
  --type <string>        create/attach: media-descriptions | entities | face-analysis | rich-transcripts | deepface-local | image-ransac | face-cluster | basic-clip | audio-fp | basic-clap | voice-print
  --local                create a local index instead of a tinycloud-backed index
  --description <string> create: human description
  --prompt <string>      create entities: free-text extraction prompt
  --schema <string>      create entities: path to a JSON schema file
  --to <string>          add: target index id/name
  --from <string>        remove: index id/name to remove the video from
  --all                  add: register every video the case has captured or sensed (watch/listen/face)
  --force                add: re-submit to the remote index even when the local mirror already lists the video as a member (reconciles a stale membership cache after server-side deletes/failures)
  --batch <number>       add --all: submission wave size — pauses between waves until the previous wave stops processing (default 12; 0 = single unpaced pass)
  --remote               list: also query tinycloud for all account indexes
  --no-upload            add: don't upload (use an already-uploaded source)
  --no-download          add: don't materialize the source locally
  --limit <number>       entities: max entities
  --offset <number>      entities: entity offset
  --pooling <string>     create basic-clip/basic-clap: pool video frames / audio windows by max | mean
  --granularity <string> create basic-clip/basic-clap: video (one vector/file) | frame (moment-level / audio windows)
  --sampling <string>    create basic-clip: uniform | shots (watch boundaries)
  --window <number>      create basic-clip/basic-clap: seconds per uniform sampling window / audio chunk
  --format <string>      json | md | txt
  --json                 Shorthand for --format json
```

Emits `index` records.

## Read

### `overcast ask`

Retrieves over bound case-search memory providers (local-grep always on; optional qmd) and answers with citations to record.id and media.at. Plain ask uses local-grep; use --deep or --memory qmd after `setup memory qmd` for qmd-backed local semantic search.

```
overcast ask <question> [options]

  Natural-language query over the case memory; answers with record.id + media.at citations.

Arguments:
  question         The question to answer

Options:
  --deep                 Use a provider's semantic/deep search path when available (e.g. qmd)
  --archive <string>     Answer over a global archive BUCKET's memory instead of this case (composable with --deep/--memory)
  --index <string>       Answer over a media-descriptions index (id/name, or archive:<bucket>/<index>) via tinycloud, not local memory
  --probe                With --index: semantic moment search (probe) instead of Q&A (ask)
  --scope <string>       With --index --probe: file | segment
  --memory <string>      Restrict to memory provider/backend ids (local-grep/local, qmd)
  --since <string>       Time filter (e.g. 24h, 2026-06-01)
  --verb <string>        Restrict to record kinds (comma list)
  --limit <number>       Max local passages; with --index --probe, max probe results
  --format <string>      json | md | txt
  --json                 Shorthand for --format json
```

Emits `answer` records.

### `overcast brief`

Story-first case brief, short by default: Verdict (analyst tldr note leading; coverage/pulse/delta demoted to one meta line) → one story per line of investigation (question → answer-so-far → linked findings → latest evidence → NEXT) → unattached findings → triage queue → coverage table → newest-first record trail. --full swaps in the verbatim chronological record dump (audit). --export writes a shareable md/html artifact (format inferred from the file extension).

```
overcast brief  [options]

  Mission brief: verdict + one story per line of investigation; short by default, --full for the audit dump; --export to md/html.

Options:
  --scope <string>       Filter, e.g. since:24h or verb:watch
  --full                 Include the full verbatim record timeline (audit dump) instead of the compact appendix
  --export <string>      Write a report file (.md or .html)
  --theme <string>       HTML export theme: plain | csi (default: plain)
  --format <string>      json | md | txt
  --json                 Shorthand for --format json
```

Emits `brief` records.

## State

### `overcast archive`

A bucket is a case-shaped folder reusable from ANY case: `init <bucket>` creates it; `add <ref...> --to <bucket>` saves local files / URLs / case records into it (sha256-deduped capture records with tags/notes/origin provenance; `--all` archives every captured/sensed media record of the active case); `list`/`show <bucket>` inspect; `remove <item> --from <bucket>` retires an item. `setup <bucket>` is the index wizard (plan/--yes): stand up local DBs (deepface-local/basic-clip/image-ransac/audio-fp/basic-clap/voice-print/face-cluster) and/or remote Cloudglue collections (media-descriptions/face-analysis/entities) plus a memory backend, backfilling existing bucket media. From any case: sense media in place via `watch archive:<bucket>/<item>`, pull a copy via `capture archive:<bucket>/<item>`, query bucket indexes via `--index archive:<bucket>/<index>` (face/similar/image/audio/voice/cluster/ask), and ask over the bucket via `ask --archive <bucket>`.

```
overcast archive <action> [arg]... [options]

  Global cross-case media archive: save media into named buckets under ~/.overcast/archive (init/list/show/add/remove/setup).

Arguments:
  action           init | list | show | add | remove | setup
  arg              bucket (init/show/setup) · media refs/record ids (add) · item + setup subcommand

Options:
  --to <string>          add: target bucket (default: the sole bucket)
  --from <string>        remove: bucket holding the item (default: the sole bucket)
  --all                  add: archive every captured/sensed media record of the active case
  --tags <string>        add: comma-separated tags stored on the archived item
  --note <string>        add: note text stored on the archived item
  --sense <string>       add: comma-separated senses to run in the bucket after adding (watch, listen)
  --keep-file            remove: keep the media file (retire the record only)
  --limit <number>       show: max items listed
  --name <string>        init/setup: bucket display name / purpose
  --index <string>       setup: comma-separated indexes to stand up (name:type or id:type:name)
  --remove-index <string> setup: comma-separated index ids/names to remove
  --signals <string>     setup: comma-separated signals for new indexes/routes
  --memory <string>      setup: local memory backend for ask --archive (local-grep | qmd)
  --video <string>       setup: comma-separated extra videos/URLs to route into indexes
  --folder <string>      setup: comma-separated local media folders to route into indexes
  --auto-index-new       setup: automatically index newly added media
  --no-auto-index-new    setup: disable automatic indexing of new adds
  --no-index             setup: save setup without starting index ingestion
  --dry-run              setup: preview without saving or applying
  --yes                  setup: non-interactive apply
  --json                 JSON output
  --format <string>      json | md | txt
```

Emits `archive` records.

### `overcast target`

A target is a line of investigation. `add --question` records what would resolve it; `close <id> --as answered|dead-end --note` marks the line done (closed lines stop seeding scan/monitor); `reopen <id>` reactivates it. Status feeds the brief/status thread cards.

```
overcast target <action> [value] [options]

  Define/refine the standing scope, a.k.a. a line of investigation (add|list|rm|show|close|reopen). Persisted to .overcast/target.json.

Arguments:
  action           add | list | rm | show | close | reopen
  value            target value (for add) or id (for rm/close/reopen)

Options:
  --image                Treat the value as a reference image path
  --question <string>    add: what would resolve this line of investigation
  --as <string>          close: answered | dead-end
  --note <string>        close: why (answered how / why it's a dead end)
  --json                 JSON output
  --format <string>      json | md | txt
```

Emits `target` records.

### `overcast source`

Register where to look (add <type>:<ref> | list | enable|disable <id> | rm <id>).

```
overcast source <action> [value] [options]

  Register where to look (add <type>:<ref> | list | enable|disable <id> | rm <id>).

Arguments:
  action           add | list | enable | disable | rm
  value            <type>:<ref> (add) or source id

Options:
  --name <string>        Friendly name for the source
  --json                 JSON output
  --format <string>      json | md | txt
```

Emits `source` records.

### `overcast note`

Creates a primary human-authored `note` record. Notes are searchable by `ask`, included in `brief`, visible in `case records`, and can cite media via `--ref <record-id|capture-id|path|url>` plus `--at <seconds|start-end|timecode>`. Use `--tag` for comma-separated labels and `--confidence` for the analyst's confidence marker.

```
overcast note <text> [options]

  Add a human observation/finding to the case, optionally anchored to evidence.

Arguments:
  text             Observation/finding text

Options:
  --ref <string>         Evidence record id, capture id, media path, or URL to anchor this note
  --at <string>          Anchor time: seconds, hh:mm:ss, or start-end span
  --tag <string>         Comma-separated labels (e.g. vehicle,contradiction)
  --confidence <string>  Analyst confidence marker (e.g. low|medium|high)
  --title <string>       Short note title
  --format <string>      json | md | txt
  --json                 Shorthand for --format json
```

Emits `note` records.

### `overcast finding`

Creates manual findings and lists/reviews automated findings. Score/text triggers emit `suggested` findings (leads) that stay OUT of memory/brief evidence until reviewed — `finding list --state triage` queues them newest-first, `accept` promotes a lead into evidence, `dismiss` rejects it (a dismissed suggestion never re-fires for the same match). Review records reference the original finding; dismissed findings remain auditable. NOTE the asymmetry: only AUTOMATED leads are quarantined. `finding create` is the operator's own promotion act — it writes an `open` finding that is evidence immediately, with no review step. The guarantee is deliberate + attributed + reversible, not reviewed: meta.provider records who ran it (`human` at the CLI/TUI, `agent` via the agent tool), `--note` on accept/dismiss records why, and `dismiss` retracts a created finding from evidence.

```
overcast finding [action] [id] [options]

  Create and review findings (create|list|accept|dismiss).

Arguments:
  action           create | list | accept | dismiss (default: list)
  id               finding id for accept/dismiss, or text for create

Options:
  --state <string>       list: open | suggested | accepted | dismissed | all | triage (open+suggested), or a comma-list
  --target <string>      create/accept/dismiss: the target line this finding supports (id or value; stamps target_id so it renders in that line of investigation)
  --note <string>        accept/dismiss: why — the review rationale, recorded on the review record for the audit trail
  --ref <string>         create: source record id, capture id, media path, or URL
  --at <string>          create: evidence timestamp seconds, hh:mm:ss, or start-end
  --confidence <string>  create: confidence marker or score
  --json                 Shorthand for --format json
  --format <string>      json | md | txt
```

Emits `finding` records.

### `overcast case`

A case is the cwd folder + its .overcast/ store. `case init [dir] --name` stands it up; `case setup` runs/saves first-run setup and `case setup status|show|edit|plan` manages it; `case status` prints the mission board (lines of investigation + triage + coverage) over setup/store/memory health; `case info` shows state; `case records [--verb] [--since]` lists records; `case memory <list|get|search|index> [q]` routes to the bound memory providers. `case clear` previews what would be lost; add `--yes` to clear records/media/state and configured materialized memory indexes while preserving the case id. `case memory get <id>` returns a field manifest (sizes); add `--field <name> [--offset N] [--limit M]` to page a large field (e.g. a watch `content`) in full — never head/tail the raw jsonl.

```
overcast case <action> [sub] [arg] [options]

  Inspect/manage the current case: init | setup | status | info | records | memory | clear.

Arguments:
  action           init | setup | status | info | records | memory | clear
  sub              setup/memory subcommand, or dir for init
  arg              record id (memory get), query (memory search), or index action

Options:
  --name <string>        Case name (init/setup/edit)
  --target <string>      setup/edit: comma-separated target values to add
  --image-target <string> setup/edit: comma-separated reference image targets to add
  --face-ref <string>    setup/edit: alias for --image-target for face matching references
  --remove-target <string> setup/edit: comma-separated target ids/values to remove
  --note <string>        setup/edit: note text to add as local evidence; pass JSON array or newline-separated text for multiple notes
  --source <string>      setup/edit: comma-separated source specs (<type>:<ref>) to add
  --remove-source <string> setup/edit: comma-separated source ids/specs to remove
  --index <string>       setup/edit: comma-separated indexes (name:type or id:type:name)
  --remove-index <string> setup/edit: comma-separated index ids/names to remove
  --signals <string>     setup/edit: comma-separated signals for new indexes/videos
  --provider <string>    setup/edit: comma-separated provider choices (<verb>:<choice>) for this case
  --provider-indexable <string> setup/edit: comma-separated provider output verbs eligible for memory/indexing
  --auto-sense <string>  setup/edit: comma-separated senses to run on newly captured media
  --auto-index-new       setup/edit: automatically add newly analyzed media to configured indexes
  --no-auto-index-new    setup/edit: disable automatic indexing for newly analyzed media
  --findings <string>    setup/edit: automated finding workflow (suggest | review | off; default suggest)
  --findings-threshold <string> setup/edit: comma-separated score-trigger floors (face=75,similar=85,cluster=70,voice=80,image_inliers=1,audio_margin=1)
  --findings-forensics <string> setup/edit: forensic flag triggers (on | off; default on) — exif editing-software + verify invalid-provenance leads
  --video <string>       setup/edit: comma-separated local videos/URLs to route
  --folder <string>      setup/edit: comma-separated local media folders to remember
  --no-index             setup/edit: save setup routes without starting remote collection ingestion
  --dry-run              setup/edit: preview without saving or applying
  --verb <string>        Filter records by kind
  --since <string>       Time filter (e.g. 24h, 2026-06-01)
  --export <string>      Write a case status/log report (.md or .html)
  --full                 status: append the raw payload JSON for auditing
  --theme <string>       HTML export theme: plain | csi (default: plain)
  --field <string>       Payload field to read in full (memory get)
  --offset <number>      Start char offset when paging a field (memory get)
  --limit <number>       Max records/passages, or max chars when paging a field
  --memory <string>      Memory provider/backend for case memory index (e.g. local-grep, qmd)
  --yes                  Confirm destructive case clear or non-interactive setup apply
  --json                 JSON output
  --format <string>      json | md | txt
```

Emits `case` records.

## Config

### `overcast prebrief`

A lightweight case kickoff. Initializes the .overcast/ store, sets the case name, and optionally seeds a target (--target) and a source (--source <type>:<ref>).

```
overcast prebrief [name] [options]

  Stand up a case: name + target + source in one shot (non-interactive via flags).

Arguments:
  name             Case name

Options:
  --target <string>      Seed target (name/prompt)
  --source <string>      Seed source <type>:<ref>
  --json                 JSON output
  --format <string>      json | md | txt
```

Emits `prebrief` records.

### `overcast setup`

Configure and persist profiles under ~/.overcast/profiles/. `setup provider <verb> <spec>` binds a verb to a provider (exec:<cmd> | http(s)://… | inproc:<module>). `setup llm <provider> <model>` sets the brain. `setup memory <local-grep|qmd>` configures case search. `setup show` prints the active profile.

```
overcast setup [action] [a] [b] [options]

  Bind the brain LLM + per-verb providers and manage profiles (setup provider|llm|memory|show).

Arguments:
  action           provider | llm | memory | show (default: show)
  a                verb (provider), provider id (llm), or backend (memory)
  b                spec (provider), model (llm), or command (memory)

Options:
  --profile <string>     Profile name to write (default: default)
  --json                 JSON output
  --format <string>      json | md | txt
```

Emits `setup` records.

### `overcast provider`

`provider setup plan|apply|show` configures catalog-backed provider choices for a profile. `provider install <path|tarball>` installs a third-party provider package (a provider.json manifest + scripts) — `provider create <name> --kind sense|source` scaffolds one, `list --installed` / `remove <name>` manage them. `provider init <verb>` runs the bound provider's init step; `provider list` shows the active bindings.

```
overcast provider [action] [verb] [options]

  Run provider setup/init hooks, or list/describe bound providers (provider setup|init|list|describe).

Arguments:
  action           setup | install | remove | create | init | list | describe (default: list)
  verb             setup subcommand, verb to init/describe, or the install path / package name

Options:
  --profile <string>     Profile name to write/read (default: active/default)
  --verb <string>        provider setup: verb to configure
  --choice <string>      provider setup: catalog choice id
  --preset <string>      provider setup: preset id (owl-local|elevenlabs|fal|hf|local-models|cloudglue|deepface-local|basic-clip|audio-fp|basic-clap|voice-print|playwright)
  --yes                  confirm a mutating action (setup apply / install / remove)
  --installed            provider list: show installed provider packages
  --upgrade              provider install: replace an already-installed package of the same name
  --kind <string>        provider create: sense | source (default: sense)
  --out <string>         provider create: output directory (default: ./)
  --json                 JSON output
  --format <string>      json | md | txt
```

Emits `provider` records.

### `overcast doctor`

Preflight: check pi version, ffmpeg/ffprobe, Cloudglue creds, tinycloud, provider bindings.

```
overcast doctor  [options]

  Preflight: check pi version, ffmpeg/ffprobe, Cloudglue creds, tinycloud, provider bindings.

Options:
  --sources              Also check configured source-provider credentials
  --json                 JSON output
  --format <string>      json | md | txt
```

Emits `doctor` records.

### `overcast skills`

`skills generate` (re)writes shipped skills including skills/overcast/{SKILL.md,reference/verbs.md}, skills/overcast-init, and focused workflow examples from the verb registry. `skills install [--harness claude-code]` copies them into the Claude Code skills dir by default; `skills install --dest <dir>` is the explicit path for Codex, Cursor, and other agents.

```
overcast skills <action> [options]

  Generate shipped overcast skills + reference from the registry, or install into a harness/directory.

Arguments:
  action           generate | install

Options:
  --harness <string>     Target harness for install (claude-code)
  --dest <string>        Install shipped skills into this directory (recommended for Codex/Cursor/other agents)
  --json                 JSON output
  --format <string>      json | md | txt
```

Emits `skills` records.
