# chirami design

Select Japanese text anywhere; a small card pops up above the pointer with
furigana, romaji and a speaker, and on click the word's parts, dictionary
entries with pitch accent, and its kanji, each kanji opening a page of its
own. Offline first; jisho.org only when the offline dictionary misses a word
with kanji, never for kana.

Goals: one Go binary per OS, fast (lookups in microseconds, a card in a few
ms), low memory (data files are mmap'd, nothing big on the heap), and
correct for a learner: every reading, label and ranking comes from a ported
reference implementation or a published dataset, tested against it.

## Packages

| path | what |
|---|---|
| `cmd/chirami` | CLI: `run`, `setup`, `show`, `render`, `lookup`, `ocr` |
| `internal/app` | debounce, page stack (word view, kanji pages), hover and tips, placement, hide policy |
| `internal/card` | pure-Go renderer: model -> RGBA image + clickable regions with tips |
| `internal/analyze` | text -> words with furigana and romaji, dictionary lookups, inflection parts |
| `internal/grammar` | Yomitan's Japanese deinflector, ported with its test suite |
| `internal/jp` | script detection, kana conversion, romaji (WanaKana port), morae |
| `internal/morph` | mmap'd IPADIC tokenizer, a port of kagome's lattice; `mkmorph` builds morph.bin |
| `internal/dict` | mmap'd JMdict + KANJIDIC2 + kanjium pitch + JmdictFurigana + JLPT + KRADFILE/RADKFILE; `build` fetches and builds dict.bin |
| `internal/jisho`, `internal/speech`, `internal/paths` | online fallback, TTS, data dirs |
| `internal/platform` | the Backend contract; `darwin` (cgo AppKit + AX, screenshot shortcut watch), `wayland` (hand-written wire client, layer-shell, data-control, niri screenshot events) |
| `internal/ocr` | client for the OCR helper: length-prefixed PNG in, one JSON line out, started on demand, stopped when idle |
| `macos/ocr` | the macOS helper: Live Text (VisionKit), Swift-only |
| `cmd/chirami-ocr`, `internal/ocr/onnx`, `internal/ocr/fetch` | the Linux helper: meikiocr's detector and recognizer plus manga-ocr for vertical text, through onnxruntime, models pinned by hash and memory-mapped in ORT format |

## Card rules

- The collapsed card answers only "how do I read it": selection, furigana,
  romaji, speaker. Everything else is one click away.
- One large thing at a time. Three inks (text, muted, quiet) and one accent;
  the accent means sound or clickable.
- Explanations touch what they explain, appear after 200 ms of hover, and
  never resize the card or move anything (tested).
- The card opens above the pointer, so it covers text already read rather
  than the next line, and keeps the edge nearest the pointer fixed as it
  grows.

## Data files

`chirami setup` writes `morph.bin` (exported from kagome-dict/ipa, compiled
into the binary but only touched by setup) and `dict.bin` (downloaded
sources, built in a temp dir and renamed into place) under
`paths.DataDir()`. Both are little-endian with a magic and a version, read
through mmap with no up-front parsing; a version mismatch asks for
`chirami setup` again.
