Skip to content

Architecture overview

This page mirrors implementation notes maintained in CLAUDE.md. Update both when changing this subsystem.

Project layout

src/ layout — all package code lives in src/cue/. Entry points: python -m cue (dev) or run.py (frozen builds).

src/cue/
├── main.py                 # menu-bar app, hotkey, top-level worker spawn
├── popup_window.py         # customtkinter popup subprocess
├── settings_window.py      # Preferences subprocess (customtkinter)
├── settings_model.py       # pure-logic layer for Preferences (stdlib only, unit-testable)
├── recorder.py             # ocap subprocess wrapper + rotator/evictor/digest threads
├── pruner.py               # MKV → keyframe extractor (own subprocess for GStreamer env)
├── ocap_launcher.py        # ocap CLI wrapper that monkey-patches the pipeline
├── digest.py               # 5 s digest tick — Haiku/Gemma 4 over keyframes + events
├── llm.py                  # DigestBackend Protocol + CloudVisionBackend + LocalVisionBackend
├── llama_server.py         # bundled llama-server subprocess lifecycle
├── local_models.py         # pinned Gemma 4 manifest + resumable download
├── frame_select.py         # 10-frame selector with anchor protection + dedupe
├── image_preprocess.py     # 896 px JPEG q75 + EXIF/ICC strip
├── prompts.py              # single source of truth for every Claude prompt
├── memory.py               # Opus rewrites memory.md from recent digests
├── suggest.py              # hotkey path: Opus + memory + recent context
├── pii.py                  # Presidio scrub() + scrub_strict()
├── pii_recognizers.py      # Cue-specific Presidio recognizers
├── privacy.py              # PrivacyMonitor + PauseController
├── overlay.py              # red-border overlay dispatcher
├── store.py                # SQLite — sessions, digests, BLOCKED_APPS, backfill_scrub
├── config.py               # CONFIG_DIR, get_api_key, streaming_config, privacy_config
├── fs.py                   # secure_dir / secure_file (POSIX chmod, Windows no-op) + Spotlight opt-out
├── capture.py              # mss + Pillow screenshot (cross-platform)
└── platform/
    ├── __init__.py         # facade — import from `cue.platform`, never directly
    ├── macos.py            # rumps tray, CGEventTap, AppleScript, Carbon, AX
    ├── windows.py          # pystray tray, pynput, UIA, SetWinEventHook
    ├── overlay_macos.py    # NSPanel per NSScreen, NSFloatingWindowLevel
    └── overlay_windows.py  # Tk Toplevel per monitor, WS_EX_LAYERED|TRANSPARENT

Process model

graph TB
    subgraph "Cue main process (menu bar / tray)"
        Main[cue.main]
        Hotkey[hotkey listener<br/>CGEventTap / GlobalHotKeys]
        Privacy[PrivacyMonitor + PauseController]
        Recorder[recorder.py rotator/evictor/digest threads]
    end

    subgraph "Subprocesses"
        Popup[popup_window<br/>customtkinter]
        Settings[settings_window<br/>customtkinter]
        Ocap[ocap-macos / ocap-windows<br/>GStreamer pipeline]
        Pruner[pruner worker<br/>per-chunk MKV reader]
        LlamaServer[llama-server<br/>localhost only, opt-in]
    end

    Main --> Hotkey
    Main --> Privacy
    Main --> Recorder
    Hotkey -- "Shift+Space" --> Popup
    Main -- "Preferences..." --> Settings
    Recorder -- "spawn / SIGKILL" --> Ocap
    Recorder -- "per-chunk" --> Pruner
    Recorder -- "5 s tick → cue.llm" --> LlamaServer

The menu bar process owns the hotkey listener, privacy monitor, recorder threads, and the popup/settings subprocess management. Heavy or risky work is in subprocesses: ocap (GStreamer), pruner (MKV decode + dhash), llama-server (multimodal inference). The menu bar is small and fast — never blocks the GUI run loop on a Cue worker.

Data directory

Single source of truth: cue.config.CONFIG_DIR. Never define platform paths elsewhere — import CONFIG_DIR.

Platform Path
macOS ~/Library/Application Support/Cue/ (data) + ~/Library/Caches/Cue/ (streaming, GStreamer-friendly)
Windows %LOCALAPPDATA%\Cue\

See Data on disk for the file-by-file table.

Shared modules

These are the modules that both platforms import without sys.platform guards:

Module What it does
cue.capture Screen capture via mss + Pillow (thread-safe).
cue.fs secure_dir() / secure_file() for permissions + mark_not_indexed() (Spotlight / Search opt-out).
cue.config CONFIG_DIR, get_api_key, streaming_enabled, streaming_config, privacy_config.
cue.recorder start() / stop() / is_running() / snapshot_context() / recent_mcap_paths() + stop_for_pause / resume_after_pause.
cue.pruner process_chunk() (own subprocess) + recent_keyframes() + evict_older_than() / evict_newer_than(). Also runs as python -m cue.pruner worker.
cue.digest read_digest() for hotkey path + evict_entries_newer_than(cutoff_ns) for the privacy purge cascade.
cue.privacy start() / stop() / toggle_manual() / is_paused() / reasons() / reason_label() / reload_browser_auth().
cue.overlay show() / hide() dispatching to cue.platform.overlay_*.
cue.settings_model Pure-logic layer for Preferences. stdlib-only, unit-testable.
cue.settings_window Preferences subprocess entry point.

Cross-platform discipline

Cue runs on macOS and Windows. Every feature, fix, or behavioral change must be applied to both. See the Cross-platform rule for the PR checklist.

See also