# `beecast`

**beecast** turns an [asciinema](https://asciinema.org) `.cast` recording into a **single, fully self-contained `.html` file** that plays in any browser — online, offline, from a web server, or straight off a `file://` path. Zero network requests, zero external dependencies, zero console errors or warnings. If you `Save` the page from a browser and open the copy on a plane, it works exactly the same.

```
beecast build demo.cast            # → demo.html, next to the cast
open demo.html                     # play it — fully offline
```

## What the page gives you

- **Playback** of asciicast v1, v2, and v3 recordings, via beecast's own inlined clean-room player (MIT, like everything else here).
- **Title and summary** — rendered from the optional metadata sidecar (see below).
- **Chapter navigation** — one button per chapter, plus markers on the player timeline.
- **Speed up / slow down** — 0.5× · 1× · 1.5× · 2× · 3×, switchable mid-playback.
- **Deep links** — share a link to an exact moment, optionally with your own comment:

  ```
  demo.html?t=93.5
  demo.html?t=1:33.5&note=Here+is+where+the+build+goes+red
  ```

  Deep links use **URL query parameters**, not fragments or server routes, so they keep working when the file is opened locally. The page has a *copy link at current time* button with an optional comment field; the linked-to comment is shown as a banner and the player is parked (poster frame) at the linked timestamp.

## The metadata sidecar

Playback works with the bare `.cast` alone. To get a title, a summary, and chapters, put a JSON sidecar next to the recording — `demo.cast` → `demo.meta.json` — or point at any file with `--meta`. The shape is defined by the [`beecast-dto`](../dto) crate (the source of truth); its human rendering is [`dto/SCHEMA.md`](../dto/SCHEMA.md) and the formal schema is [`dto/schema/beecast-meta.schema.json`](../dto/schema/beecast-meta.schema.json):

```json
{
  "title": "Rebuilding the parser",
  "summary": "One sentence on what the recording shows.",
  "chapters": [
    { "t": 0,     "title": "Setup" },
    { "t": 42.5,  "title": "First failing test" },
    { "t": 187.0, "title": "Green build" }
  ]
}
```

The timekey `t` is **seconds into the recording** — fractional values are welcome — and the first chapter **must** start at `t: 0`. Chapters are strictly ascending. Unknown JSON fields are rejected loudly, per the house rule that typos must die at parse time.

Sidecars are written by hand or generated by [SeeCast](../seecast/README.md), the AI annotator that lives in this repo under `seecast/`.

## CLI

```
beecast build <recording.cast> [--meta <file.json>] [-o <output.html>]
beecast schema        # print the metadata JSON Schema to stdout
beecast help [topic]  # topics: build, schema, exitcodes
beecast version
```

- `--meta` defaults to `<recording>.meta.json` when that file exists.
- `-o -` writes the HTML to stdout (data on stdout, diagnostics on stderr — always).
- Human at a TTY gets human-readable output; `--json` (or a piped/captured stdout) gets a two-space-indented single-key JSON document with a request-specific variant: `{ "Built": { output, bytes, cast_version, chapters, meta, warnings } }`, `{ "Version": { … } }`, and on failure `{ "Error": { message, stage } }` where `stage` is `usage` or `request`. Warnings land on stderr *and* in the JSON.
- Exit codes: `0` success, `1` failure, `2` usage, `130` interrupted. `beecast help exitcodes` prints the table; a broken pipe ends the program quietly.
- Color at a TTY by default; `--color=never`, `--color=no`, or `NO_COLOR` turn it off.
- `beecast schema` is also the codegen script: it prints the schema generated from the `beecast-dto` Rust types, which a test in that crate pins byte-for-byte to the shipped file.

## Not this tool's job

| Absent on purpose            | Where that job IS done                                    |
| ---------------------------- | --------------------------------------------------------- |
| Recording a terminal session | `asciinema rec` (or any asciicast v1/v2/v3 producer)      |
| Writing the metadata sidecar | By hand, or [SeeCast](../seecast/README.md) in `seecast/` |
| Editing / trimming a cast    | `asciinema` tooling and text editors — casts are NDJSON   |
| Serving or hosting the page  | Any static file host; the page is one self-contained file |

## Installing

```
cargo install beecast                                      # from crates.io
cargo install --git https://github.com/dkorolev/beecast   # from git
cargo install --path cli                                   # from a checkout (workspace root)
```

## License

beecast is MIT (text in [`LICENSE`](LICENSE), shipped with the crate) — all of it. The inlined player is beecast's own clean-room [`beecast-player`](../player) (see [`../player/README.md`](../player/README.md)), so no third-party code or license ships in the binary or in any generated page.
