# Extraction boundary Omasnip has four small layers: 1. `snippet-input` accepts one bounded UTF-8 source from a file, stdin, or the Wayland text clipboard. Clipboard input may use the focused Hyprland window title only as a filename hint. 2. `text-card` detects syntax, applies the active Omarchy palette, and renders both the live card frame and the final share image. `card-style` owns the deliberately small frame-preset vocabulary; `background` paints the bounded mesh/custom backdrop and soft card shadow. Custom image decoding is kept off the UI thread. `text-card-modal` owns modal motions, edits, undo cursors, and the yank register. The displayed filename may be blank; a separate, private syntax filename retains the last committed extension so hiding chrome text does not change highlighting. 3. `snippet-editor` places the same source editor over that frame in either a layer-shell overlay or an ordinary window. It watches Omarchy's stable current-theme directory across atomic theme replacements and reapplies the palette without disturbing the draft. Presentation switching serializes only the bounded draft state needed by the successor. A private `SIGUSR1` relay crosses onto the Qt event loop through a nonblocking self-pipe so a compositor-level `Ctrl+D` binding can toggle the shadow without synthesizing or corrupting keyboard modifier state. 4. `output` encodes PNG output on a worker. That image may go to `wl-copy`, a saved file, or a private annotator handoff. `omasnap-roundtrip` owns the narrow Omasnap-specific bridge: a private source-state sidecar, the clean card PNG, the adjacent Omasnap operation log, and a session-scoped Omasnap recents directory used as the commit channel. An optional fifth, deliberately shallow layer lives under `packaging/omarchy/`. Its QML is loaded by the separate `omarchy-shell` process and only launches Omasnip in fullscreen or window mode. It does not hold draft state or duplicate input, editing, rendering, output, or annotator logic. The repository-level plugin manifest lets this companion and the native application ship together while keeping their process boundary explicit. The image boundary stays explicit, with one optional editable-log return path: ```text file / stdin / clipboard | v editable Omasnip source | v flattened share PNG ---> configured screenshot annotator ^ | | | Omasnap Copy/Save only +---- same source + <-----+ editable operation log newly rendered PNG ``` The annotator never receives source or modal-editor state. For an executable named `omasnap`, Omasnip launches a tracked process with a private `OMASNAP_RECENT_DIR`, hides instead of closing, then imports the operation log that Omasnap already writes when Copy or Save completes. Omasnap presentation switches replace its process, so Omasnip also follows the existing Omasnap instance lock before deciding the session ended. Canceling produces no new log and leaves the last committed one untouched. Before the next handoff, Omasnip replaces only `card.png` and updates the log's top-level preview dimensions. Operations remain opaque Omasnap JSON and retain their IDs, undo index, and vector geometry. They are pixel-anchored; Omasnip does not attempt to semantically reflow annotations when source edits change layout. Every other annotator remains replaceable and consumes the same one-way PNG handoff as before. ## What was extracted The card renderer and modal key machine began as MIT-licensed Omasnap components. Screenshot-editor state machines, capture types, annotation code, and capture dependencies were not carried over. The round-trip bridge reads and writes Omasnap's public adjacent JSON document as opaque data and observes its existing runtime lock; it does not link Omasnap or reproduce its editor. ## Threading The GUI thread owns Qt widgets, card layout, and painting. Potentially blocking work runs through `QtConcurrent`: input subprocesses during startup, Hyprland probing and rule registration, theme-file reloads, session/operation-log I/O, PNG encoding, `wl-copy`, and disk writes. Tracked annotator launch is asynchronous through `QProcess`. All subprocess calls use argument arrays rather than a shell and have bounded waits where Omasnip owns their lifetime. ## Presentation handoff Layer-shell and xdg-toplevel are different Wayland roles and cannot safely be mutated on a mapped surface. `Ctrl+W` therefore writes an owner-only JSON draft, starts `omasnip --handoff-state …` with the opposite presentation flag, and closes the predecessor only after the successor starts. The receiving process deletes the state file as it reads it.