screenpipe regression testing checklist
August 24, 2026 · View on GitHub
purpose: prevent regressions. test core features rigorously every time
critical edge cases (sorted by regression frequency)
1. window overlay & fullscreen spaces (macOS)
1.1. Live Text Interaction (macOS)
commits: e9c76934, 9acdf850
-
Native Live Text selection — On macOS, verify that native Live Text selection works within the app's text overlay.
-
Native Data Detectors — On macOS, verify that native data detectors (e.g., phone numbers, addresses, dates) are active and clickable within the app's text overlay.
-
Cross-architecture Live Text compilation — On both x86_64 (Intel) and arm64 (Apple Silicon) macOS machines, verify that Live Text functionality is available and works without compilation errors or runtime issues.
-
window mode CSS restore — In window mode (not fullscreen), verify that CSS styling is correct and as expected (e.g., no unexpected transparent panels).
-
keyboard input in main window from tray — Open the main window from the tray icon and immediately try typing. Verify that keyboard input works without requiring a click.
-
WKWebView keyboard focus recovery — Interact with embedded web views (e.g., billing, help sections), then navigate back to other UI elements. Verify keyboard focus is correctly recovered by the WKWebView.
these break CONSTANTLY. any change to window_api.rs, main.rs shortcuts, activation policy, or NSPanel code must test ALL of these.
commits that broke this area: 0752ea59, d89c5f14, 4a64fd1a, fa591d6e, 8706ae73, 6d44af13, b6ff1bf7, 09a18070
- overlay shortcut on fullscreen space — press shortcut while a fullscreen app (e.g., Chrome fullscreen) is active. overlay MUST appear on top.
- chat shortcut on fullscreen space — press chat shortcut while on a fullscreen space. chat panel MUST appear on top. Fixed: panel pre-created at startup, show uses order_front→activate order.
- chat shortcut on normal desktop — chat appears, receives keyboard focus, can type immediately.
- overlay toggle on/off — press shortcut twice. first shows, second hides. no "ghost" window left behind.
- chat toggle on/off — press chat shortcut twice. first shows, second closes.
- overlay does NOT follow space swipe — show overlay, then three-finger swipe to another space. overlay should NOT follow you (no blink-and-disappear). was broken by
MoveToActiveSpacestaying set. - no blink on show — overlay appears instantly, no flash of white/transparent then reappear. was broken multiple times (
3097872b,8706ae73,09a18070). - no blink on hide — overlay disappears instantly. no momentary reappear after hiding.
- overlay on second monitor — with 2 monitors, show overlay. it appears on the monitor where the mouse cursor is.
- window mode vs fullscreen mode — switch overlay mode in settings. shortcut still works in both modes. no crash.
- switch modes while overlay is visible — change from fullscreen to window mode in settings while overlay is showing. should not crash (
b4eb2ab4). - keyboard focus in overlay — show overlay, start typing. text input works immediately without clicking (
d74d0665,5a50aaad). - keyboard focus in chat — show chat, start typing. text input works immediately.
- escape closes overlay — press Escape while overlay is visible. it hides.
- no space jump on show — showing the overlay should NOT cause a space transition animation (
6d44af13,d74d0665). - no space jump on hide — hiding the overlay should NOT switch you to a different space.
- screen recording visibility setting — toggle "Hide from screen recordings" in settings. The overlay is visible in recordings by default and disappears only while the setting is enabled (
206107ba). - search panel focus — open search, keyboard focus is in search input immediately (
2315a39c,1f2681e3). - ghost clicks after hide — hide overlay via
order_out. clicking where overlay was should NOT trigger overlay buttons (32e1a962). - pinch-to-zoom works — pinch gesture on trackpad zooms timeline without needing to click first (
d99444a7,523a629e). - shortcut reminder on all Spaces — switch between 3+ Spaces (including fullscreen apps). reminder pill stays visible on every Space simultaneously.
- shortcut reminder on fullscreen app — fullscreen Chrome/Safari, reminder shows at top center. not just leftmost Space.
- shortcut reminder doesn't steal focus — showing reminder never takes keyboard focus from active app.
- chat on non-primary Space — switch to Space 3 (normal desktop), press chat shortcut. chat appears on Space 3, not Space 1. no Space transition animation.
- chat re-show on fullscreen Space — show chat on fullscreen Space, hide it, show again. must reappear on same fullscreen Space.
- space monitor only hides main overlay — swipe Spaces. main overlay hides. chat window and shortcut reminder are unaffected.
- space monitor doesn't race with show — show overlay via shortcut. the
activateIgnoringOtherAppscall must not trigger space monitor's hide callback. - Chat streaming UX — Verify that chat streaming uses a state-aware grid dissolve loader for a smooth user experience.
- chat always-on-top toggle — Toggle the "chat always-on-top" setting and verify that the chat window behaves as expected (e.g., stays on top of other applications when enabled). (
b6c363e5) - overlay hidden in OBS when capture protection is enabled — Verify that the overlay is NOT visible in OBS (or other screen capture tools) when "Hide from screen recordings" is enabled, and is visible when disabled. (
87d107a29) - resizable shortcut overlay — Change shortcut overlay size (small/medium/large) in settings and verify it updates correctly on all spaces. (
1e1e17171) - overlay resize support for webview fallback — Verify that the overlay can be resized even when using the webview fallback. (
d095f5994) - text selection not blocked by URL overlays — On URL-heavy pages, verify that text selection is not blocked by clickable URL overlays. (
eb9e65b4) - macOS focused-app capture with AX observers — On macOS, verify that focused-app capture works correctly when switching between applications, utilizing AX observers. (
22830119) - macOS native Live Text interaction — On macOS, verify that native Live Text interaction, including text selection and data detectors, is re-enabled and functions correctly. (
e9c76934) - Livetext single worker thread — verify no GCD thread exhaustion freeze during heavy livetext analysis. (
a3e29d42a) - VisionKit semaphore timeouts — verify no deadlocks in vision pipeline if VisionKit hangs (10s timeout). (
397f46133) - Notification panel order_out — verify no ghost clicks after hiding notification/shortcut panels. (
32fed7c8c) - Excluded windows from screenshots — Verify that windows specified in the ignore list are correctly excluded from full-monitor screenshots taken via ScreenCaptureKit (SCK). (
61212c429) - Swift overlay meeting toggle — Verify that the meeting toggle in the Swift-based overlay works correctly and reflects the recording state. (
e5e955aa6) - shortcut reminder dot anchor — with a meeting live, hover the red dot on the pill. the dot must NOT move (it stays on the bell in both states) and the transcript card drops under it. collapsed pill stays screen-centred; the expanded bar grows leftwards only. re-check at all three overlay sizes.
- shortcut reminder hover target — while collapsed, move the cursor across the top of the screen ~150pt to the LEFT of the pill. the bar must NOT pop open — only the visible pill is hover-tracked.
- shortcut reminder health states stay centred — trigger a recording failure. the "recording needs help" pill is centred on screen (not anchored right), and returns to the centred collapsed pill after recovery.
2. dock icon & tray icon (macOS)
commits that broke this area: 0752ea59, 7562ec62, 2a2bd9b5, f2f7f770, 5cb100ea
- dock icon visible on launch — app icon appears in dock immediately on startup.
- tray icon visible on launch — tray icon appears in menu bar on startup.
- dock icon persists after overlay show/hide — show and hide overlay 5 times. dock icon must remain visible every time. was broken by Accessory mode switches.
- tray icon persists after overlay show/hide — same test. tray icon must remain visible.
- dock right-click menu works — right-click dock icon. "Show screenpipe", "Settings", "Check for updates" all work (
d794176a). - tray menu items don't fire twice — click any tray menu item. action happens once, not twice (
9e151265). - tray health indicator — tray icon shows green (healthy) or yellow/red (issues) based on recording status.
- tray doesn't show false "Error" on transient issues — Under load (running many pipes, high CPU), tray icon should not flip to "Error" if recording is actually working. Only sustained errors (>2min) show red. Tests under transient DB/OCR/audio pressure. (
abc234aae) - tray on notched MacBook — on 14"/16" MacBook Pro, tray icon is visible (not hidden behind notch). if hidden, user can Cmd+drag to reposition.
- activation policy never changes — after ANY user interaction, dock icon should remain visible. no Accessory mode switches. verify with:
ps aux | grep screenpipe. - no autosave_name crash — removed in
2a2bd9b5. objc2→objc pointer cast was causingpanic_cannot_unwind. - no recreate_tray — recreating tray pushes icon LEFT (behind notch). must only create once (
f2f7f770). - tray upgrade button opens in-app checkout — Verify that clicking the tray's upgrade button correctly opens the in-app checkout experience. (
078fcfb2) - modernized tray menu — Verify the tray menu's updated layout and functionality match the modernized design. (
b6c363e5) - Recording toggle in tray — Verify that the tray menu has a single toggle to start/stop recording (replacing separate items). (
cdc1d0fd9) - Headless webview teardown — Enable Headless, close Home, and verify every app webview process exits while recording, scheduled pipes, and the existing tray icon remain active. Global shortcuts must do nothing while dormant; opening screenpipe from the tray must recreate Home and restore shortcuts.
- Headless record-only mode — Enable Headless → Record only, close Home, and verify recording and the tray remain active while scheduled pipe occurrences are consumed as no-ops. Open screenpipe from the tray and verify pipes wait for their next future schedule without a catch-up burst.
- Enterprise hidden-UI policy reversal — With enterprise hidden UI active, turn the server policy off while the app is running. Home should reopen on the next policy refresh, the dock/full tray and global shortcuts should return, and
~/.screenpipe/enterprise.jsonshould persisthide_app: false. If the user separately enabled Headless, the app should remain dormant.
3. monitor plug/unplug
commits: 28e5c247
- unplug external monitor while recording — recording continues on remaining monitor(s). no crash. log shows "Monitor X disconnected".
- plug in external monitor while recording — new monitor is detected within 5 seconds. recording starts on it. log shows "Monitor X reconnected".
- unplug and replug same monitor — recording resumes. same monitor ID reused. no duplicate recording tasks.
- unplug all external monitors (laptop only) — built-in display continues recording. no crash.
- plug monitor with different resolution — recording starts at correct resolution. OCR works on new monitor.
- "use all monitors" setting — with this ON, all monitors auto-detected. no manual configuration needed.
- specific monitor IDs setting — with specific IDs configured, only those monitors are recorded. unplugging a non-configured monitor has no effect.
- resolution change (e.g., clamshell mode) — closing MacBook lid with external monitor. recording continues on external.
- queue stats after unplug — check logs. no queue stats for disconnected monitor after disconnect.
- --use-all-monitors flag override — Verify that the
--use-all-monitorsCLI flag correctly overrides tier-based defaults (e.g., if a tier defaults to a single monitor, the flag should still enable all monitors). (bd5b94328)
4. audio device handling
- meetings-only releases configured audio devices outside meetings — Run
bun run test:e2e:meetings-only-audioon macOS and Windows. The isolated real-audio lane must observe0running devices before a manual meeting,>=1while it is active, then0within one monitor tick after stop./healthmust reportwaiting_for_meetingrather than a capture fault while idle. (#5611) - CoreAudio Process Tap selection and fallback — desktop migration V3 automatically enables
experimentalCoreaudioSystemAudioon macOS 14.4+; the Rust serde/headless default remains OFF. With it ON, System Audio uses the CoreAudio Process Tap; initial creation failures fall back to SCK, while unrecoverable runtime rebuild failures disconnect the stream so the device manager reconstructs it through normal backend selection. (75a52603b,5634664da, #5236, #5880) - CoreAudio tap does not own or perturb the meeting speaker — while screenpipe records continuously with the Process Tap, inspect the private aggregate composition and verify it contains the tap list but no
main_sub_deviceor physical output subdevice/UID (CoreAudio may materialize an emptysub_device_list). Complete 8 cold Zoom joins and 8 Slack Huddle joins with default audio; each must connect without stopping screenpipe or pressingCmd+Shift+4, and system-audio capture must remain live before and after each join. Leave at least one Zoom join silent for more than 45 seconds: zero-filled callbacks are legitimate pre-call/idle delivery and must not stop or rebuild the tap generation. (#5880) - CoreAudio tap route and signal matrix — run
cargo run -p screenpipe-audio --example coreaudio_tap_signal_probe -- 60, play a known 1 kHz tone, and switch the default output through at least one 44.1 kHz virtual device, one 48 kHz virtual device, and a 96 kHz physical device. Every route must emit 24,000-sample/500ms windows at 48 kHz, showa1000near the source amplitude and well abovea440, avoidstall:true, and keep one tap generation. Then runcargo test -p screenpipe-audio inclusion_capture_repeated_lifecycle_stress --lib -- --ignored --nocaptureto exercise repeated create/start/stop teardown. (#5880) - meeting piggyback OFF (default) — with
experimentalMeetingPiggybackoff, a meeting starts/ends with zero device-set changes: no "Meeting Tap" device, no suspensions, logs contain nomeeting_piggybackactions. - meeting piggyback ON, detected meeting — flag on ("Smart recording" in settings), ANY capture mode, macOS 14.4+: join a Zoom call with a NON-default mic selected in Zoom → within ~4s a "Meeting Tap (output)" session stream starts, and within ~6s (two confirmation ticks — we never race the app's own device acquisition) the Zoom-selected mic is capturing; the global "System Audio (output)" stream and non-resolved mics are suspended; transcripts attribute to "Meeting Tap"/the resolved mic; on meeting end everything reverts and the resolved mic is NOT left in enabled devices (settings unchanged).
- meeting apps always keep the mic (calm near-end) — flag on, AirPods (or any BT mic) as the enabled/default mic: join a Google Meet/Zoom call and stay in it 10+ minutes, then switch mics inside the app a few times. The app must NEVER lose its microphone ("can't connect to microphone", capture dying) and the logs must show ZERO screenpipe open/close cycles of the app's current mic during the call — no per-tick
starting recording/Stopping devicechurn on it, no suspend/resume oscillation of the other mics (displacement is a one-shot latch), and any failed mic open retries at 10s/30s/60s backoff, never every 2s. (Root cause 2026-07-07: the old near-end opened the resolved mic the tick it appeared and re-evaluated displacement per tick — each cycle a real BT open/close → SCO renegotiation storm that starved Meet/Zoom; seeMicFollowinmeeting_piggyback.rs.) - piggyback takes precedence over capture mode — flag on, capture mode "always" (continuous): joining a meeting engages the piggyback exactly as in meetings-only (Meeting Tap + resolved mic, global output and non-resolved mics suspended); on meeting end continuous capture resumes on the user's configured devices with no leftover session streams or suspensions.
- manual meeting piggyback (all mic-holders) — flag on, start a MANUAL meeting while an app holds the mic: within ~6s (two-tick pid adoption) a Meeting Tap session starts over ALL mic-holding processes and their resolved mics are captured; a second app opening a mic mid-meeting rebuilds the tap over the widened set (one
rebuilding taplog, NO strike, no System Audio resume/suspend churn); ending the manual meeting reverts everything. Screenpipe's own processes must never appear in the tapped set. - enabled resolved mic displaces others (D1, latched) — two mics enrolled, meeting app using one of them (no session stream needed): once the resolved mic delivers, the OTHER enrolled mic is suspended ONCE (single transcription stream, no re-suspend churn); a transient stall of the resolved mic (BT renegotiation) does NOT resume the others — they come back only when the app releases its mics, the resolved capture stays dead for 60s+, or the meeting ends; after such a lift, the meeting app recovering onto an enrolled mic re-latches displacement once.
OWNERSHIP REQUIRES DELIVERY. Smart recording is the sole capture owner for a confirmed meeting (#6072), but only while it can actually deliver:
piggyback_may_own_capture(tap_available, meeting_pid_count, tap_ever_started). Once a tap has started for the meeting, ownership is kept through any later gap — resuming there would re-create the device churn #6072 removed. Ownership is released only when the piggyback has never delivered AND cannot contend: no meeting pids (nothing is holding the devices) or no tap support on this OS.#6072 originally took ownership unconditionally, so a meeting whose tap never built recorded nothing: on 2.6.1 an 86s manual meeting produced 3,584 samples (~0.22s) and an empty transcript, while identical audio captured normally with no meeting active. Exhausted strikes deliberately still hold ownership — a meeting app really is holding devices there, so resuming needs device-level validation.
-
tap build failure keeps recording — flag on, force tap failure (revoke System Audio Recording permission) BEFORE any tap starts: the user's configured capture keeps running for the whole meeting and audio is recorded. Confirm ≤3 retries per meeting with 60s cooldown, and that
piggyback_meeting_summarydoes NOT carrycaptured_no_audio: true. -
tap build failure is backend-neutral — repeat with
experimentalCoreaudioSystemAudioON: normal capture keeps running either way, and the System Audio stream comes up on whichever backend the user's settings select. -
app quits mid-meeting — kill the meeting app: tap stream tears down within ~2s; no crash, no rebuild storm. A tap HAS started for this meeting, so suspensions are deliberately kept until the watcher ends it.
-
no pid (ui_scan/reattach) keeps recording — a DETECTED meeting whose sensor can't identify the process (ui_scan, post-restart reattach) leaves normal capture running; nothing is holding the devices, so there is nothing to contend with. Manual meetings are NOT in this bucket — they derive their pid set from the live mic-holder enumeration (see the manual-piggyback item above).
-
a gap AFTER a working tap still suspends — join a real call so the tap starts, then make the pid set go empty: suspensions must be KEPT (no resume churn). This is the anti-SCO-storm behaviour from #6072 and must not regress while fixing the silent-meeting case.
-
silent meetings are detectable — if a meeting ever DOES capture nothing,
piggyback_meeting_summarymust carrycaptured_no_audio: true. Theoutcomestrings (stable_fallback,no_pid,unavailable) are all reported for meetings that captured nothing and all read as benign, sooutcomealone cannot distinguish a silent meeting from a healthy one. -
the gate is visible in logs — with a meeting active and the flag on, released builds (INFO level) must log
smart recording owns capture for this meeting — not starting normal audio device: <device>. This used to be DEBUG, i.e. invisible in shipped builds, which is why a silent meeting left no trace anywhere. -
browser pop-out / Little Arc meeting detection — join a Google Meet call in a Chrome pop-out window or an Arc "Little Arc" window, then focus a different app: the meeting is detected within one poll of the mic being held (log shows the
UnresolvedBrowser->Activepromotion); a non-meeting window whose title merely looks like a meeting code (e.g. a doc named "abc-defg-hij") with no mic held must NOT trigger detection. (ff0337416) -
piggyback on unsupported OS — flag on, macOS <14.4 / Windows <20348: one-time "using the stable capture path" log. The meeting now genuinely rides the stable path: normal capture keeps running and audio is recorded (
outcome: unavailable, and NOTcaptured_no_audio). The Meeting Tap stream must not silently downgrade to endpoint-wide loopback. -
mid-call mic switch in the app — change Zoom's mic mid-call: capture follows within ~6s (two confirmation ticks AFTER Zoom has the new device — the app always acquires first; old session mic stops after two missed resolver ticks, new one starts); changing the OS default while Zoom is pinned elsewhere does NOT switch capture. Switching onto a mic the sweep had displaced only clears its suspension flag — no immediate restart racing the app.
-
mic switch must not flap the meeting — switch the meeting app's mic (AirPods → phone → built-in, several times):
meeting_status_changedstays active=true throughout — NO end/re-start pair ~20s after each switch, no Meeting Tap teardown/rebuild, no System Audio resume/suspend churn. (Root cause was device-derived session keys: macOS synthesized the audio-session id from the device set and WASAPI GUIDs are per-endpoint, so a mic switch re-keyed the session and the meeting rode the 20s ending grace into EndMeeting + instant restart.) -
piggyback never acts on silence — during a piggybacked call, silence must never make the piggyback rebuild, restart, probe, or notify: mute in the meeting app (or leave a silent tab rendering nothing) for 5+ min → NO notification, NO Meeting Tap rebuild, NO resolved-mic restart, and the logs contain no silence-driven piggyback actions. A silent meeting device is the user's own in-meeting feedback loop — they fix it in the app and the mic/output follow tracks the switch. (The GLOBAL System Audio tap's silence watchdog — item above,
75a52603b— is unchanged and out of scope here.) Dead-stream handling still applies: hard open failures notify once viaaudio_capture_health_mic_capture_failed, and dead capture streams retry throughMicFollow's backoff. -
Windows per-process tap supervisor — Windows 20348+: verify target-exit detection (app quits -> Meeting Tap stops and stable capture resumes) and default-endpoint loopback re-anchor for explicit global loopback. There is deliberately NO per-pid silence watchdog (see the item above — the piggyback never acts on silence). Confirm tap startup failure falls back through the user's normal/default audio settings, not through an implicit low-level endpoint-loopback downgrade inside the Meeting Tap.
-
piggyback telemetry — flag on (any capture mode): end a piggybacked meeting → one
piggyback_meeting_summaryappears in PostHog Live Events with the correct outcome; a failed meeting-mic open appears asaudio_capture_health_mic_capture_failed(there are no mic-silent events — the piggyback never acts on silence); analytics toggle OFF → nothing is sent (engineTELEMETRY_ENABLEDgate). -
default audio device — with "follow system default", recording uses whatever macOS says is default.
-
plug in USB headset — if set to follow defaults and macOS switches to headset, recording follows.
-
unplug USB headset — recording falls back to built-in mic/speakers. no crash. no 30s timeout errors.
-
bluetooth device connect/disconnect — AirPods connect mid-recording. audio continues without gap.
-
no audio device available — unplug all audio. app continues (vision still works). log shows warning, not crash.
-
audio stream timeout recovery — if audio stream times out (30s no data), it should reconnect automatically.
-
per-device audio-timeout recovery — Force one microphone timeout, then prove that only later usable microphone audio clears
active_no_data; healthy system output alone must not clear it. Repeat with system output timed out and microphone live. Verify a one-shot timeout expires before the native 90-tick alert, repeated zero-fill/receive timeouts keep the failure active, a recovered device clears immediately, an unresolved current device still raisesrecording needs help, and removing/deselecting the failed device stops it from degrading current capture. Run this after a packaged macOS display/wake transition. -
multiple audio devices simultaneously — input (mic) + output (speakers) both recording. both show in device list.
-
disable audio setting — toggling "disable audio" stops all audio recording. re-enabling restarts it.
-
Metal GPU for whisper — transcription uses GPU acceleration on macOS (
f882caef). verify with Activity Monitor GPU tab. -
Qwen3-asr OpenBLAS — On Linux/Windows, verify that qwen3-asr uses OpenBLAS for improved transcription performance. (
e64ee25f4) -
Batch transcription mode — Verify that batch transcription mode works correctly with both cloud and Deepgram engines.
-
Cloud transcription batch capping — Send large audio chunks (>200s) to cloud transcription. Verify they are correctly capped/split and do not trigger Cloudflare 413 errors. (
792145ac6) -
Lower RMS threshold for batch mode output devices — In batch transcription mode, verify that output devices correctly use a lower RMS threshold.
-
OpenAI-compatible STT connection test — Configure OpenAI-compatible STT, then use the connection test feature. Verify it accurately reports connection status.
-
OpenAI-compatible STT editable model input — When using OpenAI-compatible STT, verify that the model input fields are editable.
-
OpenAI-compatible STT with custom vocabulary — Configure OpenAI-compatible STT with a custom vocabulary. Verify that transcription accuracy improves when this vocabulary is present in the audio. Verify that vocabulary is sent as both prompt and context. (
d3a4b6bcc) -
OpenAI-compatible transcription engine support — Enable and configure the OpenAI-compatible transcription engine. Verify that audio is correctly captured and transcribed using this engine.
-
"transcribing..." only for recent chunks — Verify that the "transcribing..." caption/indicator only appears for audio chunks that are less than 2 minutes old. (
b70116b) -
no transcribing caption on old silent chunks — Verify that old silent audio chunks do not trigger or display a "transcribing..." caption. (
54a550f4) -
silent chunks deleted, not stored — After periods of silence, verify that no empty transcription rows are stored in the database for silent audio chunks, and they are instead correctly deleted. (
cb2cc205) -
silent chunk zombie loop prevention — Verify that silent audio chunks do not lead to a "zombie loop" resulting in excessive CPU usage or large log files. (
6b3a71eb) -
write-ahead transcription cache performance — Verify that the write-ahead transcription cache improves the performance and responsiveness of audio transcription. (
46350671) -
enhanced audio pipeline diagnostics — Check logs and verify that enhanced audio pipeline diagnostics provide useful and accurate information. (
2e68400c) -
audio start/stop shortcuts toggle capture — Verify that the audio start/stop shortcuts correctly toggle audio capture on and off. (
3701cce2) -
bulk import transcription dictionary — Verify that the bulk import functionality for the transcription dictionary works correctly, including smart delimiter detection. (
73adc9d4) -
Audio start/stop shortcuts — Verify that designated audio start/stop shortcuts reliably toggle audio capture on and off. Check logs for corresponding start/stop events.
-
Filter music toggle UI — Verify that a "filter music" toggle exists in recording settings and correctly enables/disables music filtering.
-
Music detection thresholds — With "filter music" enabled, play various types of music. Verify that music is correctly detected and filtered, and that non-music speech is still captured.
-
Audio reconciliation FK constraint loop — Verify that audio reconciliation does not enter an infinite retry loop on foreign key constraints. (
e9e2dc252) -
Skip reconciliation when transcription disabled — Disable audio transcription in settings. Verify that audio reconciliation is skipped. (
ceb77559d) -
read-pool pressure never costs a transcription — Put the read pool under load (open the timeline, run a broad search, run several pipes) while audio is being transcribed. Verify transcriptions still land: no insert may fail in its pre-read phase. Logs may say "cross-device dedup check unavailable"; that is the intended fail-open — a duplicate cross-device transcription is acceptable, losing the recording is not. (
SCREENPIPE-CLI-SN) -
a batch rollback is not reported as a crashed worker — When one write in a batch fails, the others are rolled back with it. Verify those log "was rolled back with its batch … retrying", not "attempted to communicate with a crashed background worker". Nothing crashed and their write was never attempted. (
SCREENPIPE-CLI-SN) -
dead System Audio auto-reconnect — Simulate a dead system audio stream. Verify it auto-reconnects and resumes capture. (
0f287761d) -
SCK System Audio dead-display recovery (clamshell) — Mid-call, close the MacBook lid with an external display attached → remote-participant (System Audio) audio resumes within ~1 min via auto re-anchor, mic unaffected. AND: leave the machine idle (nothing playing) for 10 min with stable displays → NO System Audio rebuild/churn (guards the reverted output recv-timeout
0f287761d/357e4dfcc). Watchdog:core::sck_output_watchdog(#3901). -
per-device audio toggle — In the tray menu, verify you can toggle recording for individual audio devices. (
3ee3defcb) -
per-monitor tray toggle — With 2+ displays, open the tray recording section and uncheck one monitor. Verify only that display stops screen capture; re-check resumes it. Pause one display individually, then global pause/resume — the individually paused display stays off. (
4685) -
stable audio device order — Verify that audio devices listed in the tray menu maintain a stable order across refreshes. (
4577ac8a6) -
Mic disconnect false-positives on sleep/wake — Put the computer to sleep and wake it up. Verify that no false-positive mic disconnect notifications or logs are generated. (
796baa619)
Audio device recovery (monitor unplug / device switch)
commits: device_monitor.rs atomic swap, tiered backoff, empty device list guard
- unplug monitor during active Zoom call — output audio recovers within 15 seconds. Verify:
grep "DEVICE_RECOVERY.*output.*restored" ~/.screenpipe/screenpipe-app.*.log. Verify:curl localhost:3030/search?content_type=audio&limit=5shows output device transcriptions resume. - unplug and replug monitor within 5 seconds — no audio gap. both input and output continue. Verify: no "stopping" log for input device.
- unplug monitor, wait 2 minutes, replug — output recovers both times. Verify: two
DEVICE_RECOVERYlog entries. - switch audio output (AirPods → speakers) during call — output audio continues with <5s gap. Old device kept running until new one starts (atomic swap).
- health endpoint during output recovery —
curl localhost:3030/healthshowsdevice_status_detailswith output device present within 15 seconds of recovery. - SCK transient failure doesn't cascade — if ScreenCaptureKit returns empty device list, running devices are NOT disconnected. Verify:
grep "device list returned empty" ~/.screenpipe/screenpipe-app.*.logshows warning but no disconnections. - DB gap query after device switch — run:
sqlite3 ~/.screenpipe/db.sqlite "SELECT t1.timestamp as gap_start, t2.timestamp as gap_end, (julianday(t2.timestamp) - julianday(t1.timestamp)) * 86400 as gap_seconds FROM audio_transcriptions t1 JOIN audio_transcriptions t2 ON t2.id = (SELECT MIN(id) FROM audio_transcriptions WHERE id > t1.id AND is_input_device = 0) WHERE t1.is_input_device = 0 AND (julianday(t2.timestamp) - julianday(t1.timestamp)) * 86400 > 60 ORDER BY t1.timestamp;"— should return no rows if output was continuously captured. - Bluetooth audio device hijack recovery — Join a video call (e.g., Zoom, Proton Meet) on AirPods, end the call, join another call ~1 min later on same AirPods. Verify the second call is fully captured (audio_chunks created throughout). CoreAudio sometimes delivers zero-fill when another app has exclusive claim; the watchdog detects sustained silence (>30s of exact zeros) after initial healthy audio and rebuilds the device. Regression:
a2e89b2ae(initial detection), fixed by357e4dfcc(only trip watchdog after stream is healthy). USB devices that never produce real audio should NOT trigger rebuild storms. - Manual-mode pinned-input fallback — In manual mode (NOT "Follow System Default"), pin only AirPods (input) as your mic. Mid-recording, turn off the AirPods. Verify: within ~20-25s the monitor engages the system default mic as a substitute and capture continues. Re-connect AirPods. Verify the substitute is torn down and capture returns to AirPods. Log markers:
grep "PINNED_FALLBACK" ~/.screenpipe/screenpipe-app.*.logshowspinned input '...' missing > 20s, capturing from system default '...' until it returnsthenclearing fallback '...': pinned input returned. Edge: if you also user-disabled the default mic (privacy mode), expect "system default ... is user-disabled — no fallback engaged" log + zero capture rather than auto-fallback. - Pinned-input fallback when the dead device IS the system default (or there is none) — Same as above, but make AirPods BOTH the pinned input AND the macOS default input (the common real case), then turn them off. Verify capture continues from the built-in mic within ~20-25s — NOT zero capture. The decider now fails over to any available input when the system default is unusable (it IS the dead pinned device — Bluetooth lingers as the registered default — or CoreAudio reports no default). Reconnect AirPods → substitute torn down. Sub-checks: (a) prefers an on-board mic over virtual/aggregate inputs (e.g. BlackHole/Aggregate present → built-in chosen); (b) still respects privacy — if the only other input is user-disabled, expect zero capture, not auto-fallback; (c) transient empty device list (SCK failure) → no fallback that cycle, no disconnect cascade; (d) sleep/wake flap < grace does not engage a spurious fallback. Regression:
ba23c8531(ruark 6/18 "no recording either side of the call", frames=0/samples=0 — AirPods were the only input AND the default).
meeting detection & speaker identification
commits: calendar_speaker_id.rs, meetings.rs, meeting_persister.rs
- restart during active meeting — start a 1:1 calendar meeting (2 attendees), quit app mid-meeting, relaunch. meeting re-detected via calendar event still in progress. speaker names assigned. verify:
grep "meeting detected via calendar" ~/.screenpipe/screenpipe-app.*.logshows detection after restart. verify:sqlite3 ~/.screenpipe/db.sqlite "SELECT id, name FROM speakers WHERE name != ''"shows both user and attendee names. - calendar-only meeting detection — schedule a 1:1 meeting with 2 attendees, no meeting app (Zoom/Meet) open. meeting detected purely via calendar. verify:
grep "meeting_started" ~/.screenpipe/screenpipe-app.*.log. - calendar meeting auto-end — calendar meeting detected, wait past the calendar event end time. meeting_ended fires. verify:
grep "meeting ended via calendar" ~/.screenpipe/screenpipe-app.*.log. - speaker naming in 1:1 — during 1:1 call with userName set in settings, input speaker named as user, output speaker named as other attendee. verify:
curl 'localhost:3030/search?content_type=audio&speaker_name=<attendee>&limit=5'returns results. - auto-name input speaker — with userName set, after ~2 minutes of speaking into mic, dominant input speaker named. verify:
grep "auto speaker identification: named" ~/.screenpipe/screenpipe-app.*.log. - speaker names survive restart — speaker named pre-restart stays named post-restart. verify:
sqlite3 ~/.screenpipe/db.sqlite "SELECT id, name FROM speakers WHERE name != ''"shows same speakers before and after restart. - no duplicate speaker naming on restart — restart during meeting, speakers already named aren't overwritten or duplicated. verify: no duplicate names in speakers table.
- meeting detection stability — Verify that meeting detection does not drop when alt-tabbing during long calls. (
7684f1d47) - speaker search deduplication — Search for speakers in the UI. Verify that results are deduplicated and reassignment targets are stable. (
34a62c053) - meeting detection regardless of transcription mode — Verify that meeting detection works even when transcription is disabled. (
ef39e728d) - Windows UI Automation meeting detection — On Windows, join a meeting in a supported app (Zoom, Teams, etc.). Verify detection works via UI element scanning rather than just process focus. (
fe905d6af,01eb9cf33) - macOS Zoom menu bar detection — On macOS, join a Zoom meeting. Verify detection works even if Zoom window is not focused, by scanning menu bar items. (
849372fa9) - Stop auto-detected meeting from overlay — During an auto-detected meeting, verify that the stop button in the overlay correctly terminates the meeting session. (
403d5b732) - MLX transcription model reuse — Verify that the MLX transcription model is reused across requests to prevent GPU memory spikes or crashes. (
59deeba19) - Meeting detection app coverage — Verify detection works for 35+ supported apps and various browser URL patterns. (
e6740eb38) - Meeting detection UI labels — Verify meeting status shows "starts in Xm" and filters all-day events correctly. (
ef470d9e1) - Meeting detection support for Signal, WhatsApp, Telegram, and Teams 2 — Verify that meetings from these apps are correctly detected and recorded. (
8d2f1a542,a74e393e1) - Browser meetings splitting fix — Verify that meetings in the browser are correctly split into separate events. (
d8ba1dad3) - Meeting with hidden UI controls — Start a Zoom/Teams meeting. Minimize the meeting window or switch apps (Zoom controls move out of accessibility tree). Verify meeting stays active and does NOT auto-terminate after 30 seconds. Audio output detection prevents false "meeting ended" events. (
4e784f620) - OpenAI-compatible transcription endpoint — Verify that the
/v1/audio/transcriptionsendpoint works as expected, following the OpenAI specification. (5a14e9a92)
5. frame comparison & OCR pipeline
commits: 6dd5d98e, 831ad258
commits: 6dd5d98e, 831ad258
- static screen = low CPU — leave a static image on screen for 60s. CPU should drop below 5% (release build). hash early exit should kick in.
- active screen = OCR runs — actively browse/type. OCR results appear in search within 5 seconds of screen change.
- identical frames skipped — check logs for hash match frequency on idle monitors. should be >80% skip rate.
- ultrawide monitor (3440x1440+) — OCR works correctly. no distortion in change detection. text at edges is captured.
- 4K monitor — OCR works. frame comparison doesn't timeout or spike CPU.
- high refresh rate (120Hz+) — app respects its own FPS setting (0.5 default), not the display refresh rate.
- very fast content changes — scroll quickly through a document. OCR captures content, no crashes from buffer overflows.
- corrupt pixel buffer — sck-rs handles corrupt ScreenCaptureKit buffers gracefully (no SIGABRT). fixed in
831ad258. - window capture only on changed frames — window enumeration (CGWindowList) should NOT run on skipped frames. verify by checking CPU on idle multi-monitor setup.
- Meeting app OCR force — Open a meeting app (Zoom, Teams, Meet). Verify OCR is forced for these apps even if accessibility is available. (
b18ae2253) - Accessibility automation properties — Verify automation properties (labels, roles, automation IDs) are correctly captured in the accessibility tree across Windows, macOS, and Linux. (
1b7d0db5b) - Apple Vision per-word OCR fast path — Browse an app with lots of text (e.g., Wikipedia article with 500+ words). Verify OCR database inserts are fast (bulk VALUES insert, not 500 individual RETURNING queries). Check logs for no "Slow DB batch insert" warnings. Regression:
6f3f80dd3(Apple per-word records now use level="0" for bulk-insert fast path, not level="5" which hit expensive per-row insert). - DB write coalesce queue — Under heavy load (e.g. many pipes + high FPS), verify no "database is locked" errors and no vision stalls due to write contention. (
39c016cb3,d119d060d,231521192) - static-screen does not trigger vision-stall WARN — Sit on a Zoom call / slide deck / IDE waiting screen for >2 minutes (no UI activity). Verify the engine does NOT log
health_check: no unique vision frame in Nswarnings, and the Tauri app'sconsecutive_vision_stallcounter stays at 0 (novision capture recovered after N stale checksinfo line). Dedup-skipped captures must ticklast_db_write_tsso the health check distinguishes "static screen, dedup working" from "pipeline stuck". Pre-fix: 8–14 false alarms/day with single stretches up to 28 minutes. (a08ec9140, +follow-up commit) - capture loop survives a wedged ScreenCaptureKit call (macOS) — SCK completion handlers (
SCShareableContent,updateContentFilter,startCapture) can silently never fire while the machine is idle; every such call must be bounded so one wedged callback can never freeze the capture loop, starve the 30s idle fallback, or flip/healthframe_statustostaleon a healthy static screen (the false "recording needs help" incident). Runbun run test:e2e:capture-loop-liveness:macosand verify the app log containse2e: injecting one hung visual-change probe(the injection actually fired) whilecapture_attemptskeeps advancing. Also verify barestalealone never confirms the desktop incident before its user-presence tier (90s with fresh UI activity, 15 min idle). Live-incident evidence: 6 thread samples wedged infetch_shareable_content → pthread_join, 2026-07-26. - focus-cold display does not trigger recording-health alert (macOS) — On a multi-monitor setup, select one display for recording and work on another long enough for the selected display to enter focus-aware Cold state. Capture attempts may stop, but
capture_loop_heartbeatsmust keep advancing,/health frame_statusmust remainok, and the recording-health overlay must stay normal. Run the deterministic full-app regression withbun run test:e2e:recording-health-focus-cold:macos; it accelerates the pre-fix attempt-clock false stale transition without changing release thresholds. - gone-silent capture recovers end to end (macOS) — Run
bun run test:e2e:capture-stall-recovery:macoson a host with Screen Recording permission. The lane first pauses every selected display, verifies/health frame_status=disabledand a normal recording-health pill, resumes them, and proves capture progress returns. It then parks one SCK frame worker and proves the bounded, unfiltered CoreGraphics escape hatch can reach a real terminal capture outcome; its isolated seed clears window filters because production must fail closed whenever SCK window-id exclusions are active. It freezescapture_attempts, reaches/health frame_status=staleandrecording needs help, triggers exactly onegone-silent stallVisionManager restart from per-monitor detection, resumes attempts and terminal outcomes in the same app process, showsrecording again, and returns the pill to normal. A healthy terminal outcome is a write, dedup, or explicit corrupt-frame skip; failed/time-out captures remain failures and cannot satisfy the recovery proof. Unit coverage must also prove one healthy monitor cannot mask a silent sibling. The same lane parks one id-basedSCShareableContentlookup: it must return inside the bounded timeout and the next lookup must enumerate real display dimensions. The test uses isolatedSCREENPIPE_PORT=3041and a debug-onlyignore-disk-pressureseed so host free-space changes cannot replace the intended fault with a genuine safety shutdown; never point it at the developer's production instance. - Windows idle CPU reduction — Verify low CPU usage on Windows when screen is idle, using event-driven hooks and caching. (
d2c9d1fb8) - reduced CPU spikes in vision/capture pipeline — Actively browse and use applications, verifying that CPU spikes in the vision/capture pipeline are significantly reduced. (
8f7294e6) - OCR bounding boxes normalized on Windows/Linux — On Windows and Linux, verify that OCR bounding boxes are correctly normalized to the 0-1 range, ensuring consistent text overlay and interaction. (
aba74513) - Debounced monitor capture errors — Simulate transient monitor capture errors. Verify that these errors are debounced and do not lead to excessive error logging or app crashes.
- Focus-aware capture — Enable "Only record focused monitor" in settings. Verify that Screenpipe only captures frames and runs OCR for the monitor that currently has the focused window. (
886b5c05d) - no stranded WGC session after persistent-capture disable (Windows) — Force repeated persistent WGC init failures on one monitor (e.g. flaky driver, monitor sleep during init) while captures overlap (event-driven engine's capture timeout drops the future but the detached blocking closure keeps running, so two closures can race on the same monitor's shared state). After the "persistent capture disabled for monitor N" warning, verify no live WGC session remains: GPU usage for the app drops to per-frame-capture levels and no
CopyResourcework continues for that monitor. The disable path drains any concurrently stored session under the mutex, and the store path re-checks the disable flag under the same mutex — a session stored behindpersistent_capture_disabled == truewould otherwise leak GPU textures until refresh/stream release.
6. Battery Saver Mode
commits: d5a9d052, 0b32cc9a, ca29a67b
- Battery Saver mode functionality — Enable Battery Saver mode. Verify that capture adjustments (e.g., reduced FPS, paused capture) occur as expected when the device's power state changes (e.g., unplugging/plugging power, low battery).
- Faster power state UI updates — Change the device's power state (e.g., unplug/plug power). Verify that the UI updates quickly and accurately reflects the current power state and capture mode.
- Correct default power mode — On a fresh install or after a reset, verify that the default power mode is set to "performance" until Battery Saver mode is explicitly enabled or configured.
7. permissions (macOS)
commits: d9d43d31, 620c89a5, 14acf6f0
-
fresh install — all prompts appear — screen recording, microphone, accessibility prompts all show on first launch.
-
denied permission → opens System Settings — if user previously denied mic permission, clicking "grant" opens System Settings > Privacy directly (
620c89a5). -
permission revoked while running — go to System Settings, revoke screen recording. app shows red permission banner within 10 seconds.
-
permission banner is visible — solid red
bg-destructivebanner at top of main window when any permission missing. not subtle (9c0ba5d1). -
permission recovery page — navigating to /permission-recovery shows clear instructions.
-
startup permission gate — on first launch, permissions are requested before recording starts (
d9d43d31). -
faster permission polling — permission status checked every 5-10 seconds, not 30 (
d9d43d31). -
No recurring permission modal after close — Grant macOS permissions, quit the app, and relaunch it multiple times. Verify that the macOS permission modal does NOT reappear every time the app is closed.
-
Screen Recording Later preserves restart consent — Grant Screen Recording, click Later in macOS, and verify screenpipe stays open with a clear restart screenpipe button and the warning that screenpipe will not work until restarted. Only clicking that in-app button may relaunch the app. Run
bun run test:e2e:screen-recording-restart:macos. -
mic-grant restart survives a slow boot — with mic permission already granted from a prior session, relaunch with a slow boot (large DB migration or first-run model download) so the window gains focus before
ServerCorefinishes constructing. Verify capture actually starts once boot completes instead of silently staying off. Checkgrep "start_capture after mic grant" ~/.screenpipe/screenpipe-app.*.log— should show success, not "gave up after N attempts" (previously a fixed ~10s budget that raced boot and gave up permanently — found during the Intel-Mac CI smoke-test investigation, screenpipe#4978). If an attempt does time out, verify a later window focus retries rather than being silently disabled for the rest of the session (regression: the oldMIC_FOCUS_CAPTURE_RESTARTlatch was set once and never reset). -
fresh install — all prompts appear — screen recording, microphone, accessibility prompts all show on first launch.
-
denied permission → opens System Settings — if user previously denied mic permission, clicking "grant" opens System Settings > Privacy directly (
620c89a5). -
permission revoked while running — go to System Settings, revoke screen recording. app shows red permission banner within 10 seconds.
-
permission banner is visible — solid red
bg-destructivebanner at top of main window when any permission missing. not subtle (9c0ba5d1). -
permission recovery page — navigating to /permission-recovery shows clear instructions.
-
startup permission gate — on first launch, permissions are requested before recording starts (
d9d43d31). -
faster permission polling — permission status checked every 5-10 seconds, not 30 (
d9d43d31). -
improved permission recovery UX — Verify that the user experience for recovering from denied permissions is clear and intuitive. (
57cca740) -
Settings returns to normal window level after permission flow — From the full Home/Settings window, open any macOS Privacy & Security pane, return to Screenpipe, then focus another app. The other app must be able to appear above Screenpipe; only intentional overlay surfaces may remain floating. (
#5753)
8. app lifecycle & updates
commits: 94531265, d794176a, 9070639c, 0378cab1, 4a3313d3, 7ffdd4f1, 1b36f62d
- clean quit via tray — right-click tray → Quit. all processes terminate. no orphaned ffmpeg/bun processes.
- clean quit via dock — right-click dock → Quit. same as above.
- clean quit via Cmd+Q — same verification.
- force quit recovery — force quit app. relaunch. database is intact. recording resumes.
- sleep/wake — close laptop lid, wait 10s, open. recording resumes within 5s. no crash (
9070639c). - restart app — quit and relaunch. all settings preserved. recording starts automatically.
- Cross-platform autorelease pool — Verify that Windows and Linux builds compile and run without issues related to macOS-specific autorelease pool calls. (
851b3037c) - Main thread safety (macOS) — Verify that tray icon operations, space monitoring, and frontmost app restoration are dispatched to the main thread to prevent crashes. (
ac46aa437,418826dfa,274826dfa) - ObjC memory management (macOS) — Verify that all ObjC operations are wrapped in scoped autorelease pools and objects are retained in async callbacks to prevent use-after-free or SIGSEGV crashes. (
4cb9850f7,c49350df0,139500d52) - auto-update — when update available, UpdateBanner shows in main window. clicking it downloads and installs.
- update without tray — user can update via dock menu "Check for updates" or Apple menu "Check for Updates..." (
d794176a,94531265). - update banner in main window — when update available, banner appears at top of main window.
- source build update dialog — source builds show "source build detected" dialog with link to pre-built version.
- owned port release on restart — restart Screenpipe and verify its internally owned server shuts down gracefully, the shutdown is awaited, and the new server binds port 3030 after the release grace period.
- startup port owner arbitration — after the single-instance focus handoff has had its chance: (a) a healthy Screenpipe owner on 3030 or 11435 remains alive and exactly one native dialog asks the user to quit it; (b) an owner that fails the Screenpipe health probe is terminated gracefully first, forced only after the release grace period, and Screenpipe binds the released port; (c) if reclaim still fails, Screenpipe does not bind through the conflict and shows one native error dialog (
0378cab1,4a3313d3,8c435a10). - no orphaned processes — after quit,
ps aux | grep screenpipeshows nothing.lsof -i :3030shows nothing. - rollback — user can rollback to previous version via tray menu (
c7fbc3ea). - Zombie CPU drain prevention — Verify that
lsofcalls have a 5-second timeout, preventing zombie CPU drain, especially on quit. Check logs forlsoftimeouts if applicable. - Tokio shutdown stability — Verify that the
tokioshutdown process is stable and doesn't panic in the tree walker, especially during application exit or process restarts. - No ggml Metal destructor crash on quit — Perform multiple quick quits (Cmd+Q, tray quit) and restarts. Verify that the app exits cleanly without a
ggml Metal destructor crash. - Properly wait for UI recorder tasks before exit — During a clean quit, verify that all UI recorder tasks complete properly and no orphaned processes or partial recordings remain.
- recording watchdog diagnostics — Verify that the recording watchdog correctly diagnoses and handles recording issues, and provides useful diagnostic information. (
af2b4f3d) - capture stall detection — Simulate or observe a capture stall. Verify that a notification appears with a "Restart" button to recover. (
d3ead88eb) - DB write stall detection — if DB writes stall, verify a notification appears with a "Restart" button. (
1b4bf7918) - clean startup after unclean shutdown on Windows — On Windows, verify that an unhealthy owner of port 3030 is reclaimed with non-forced
taskkillfirst and/Fonly after the grace period; verify that a healthy Screenpipe owner is preserved and reported instead. (a8413fe2) - sleep/wake detection on Windows and Linux — Verify that recording resumes correctly after sleep/wake on Windows and Linux. (
f519281b5)
9. database & storage
commits: eea0c865, cc09de61, e61501da, d25191d7, 60096fb9
-
slow DB insert warning — check logs. "Slow DB batch insert" warnings should be <1s in normal operation. >3s indicates contention.
-
concurrent DB access — UI queries + recording inserts happening simultaneously. no "database is locked" errors.
-
store race condition — rapidly toggle settings while recording is active. no crash (
eea0c865). -
event listener race condition — Tauri event listener setup during rapid window creation. no crash (
cc09de61). -
UTF-8 boundary panic — search with special characters, non-ASCII text in OCR results. no panic on string slicing (
eea0c865). -
low disk space — with <1GB free, app should warn user. no crash from failed writes.
-
opt-in low-disk recording guard — the Storage toggle defaults off and persists across restart. With it off, a low-disk event leaves capture running. With it on, crossing the engine threshold stops the real capture session, leaves
/healthand authenticated search available, and persists the critical in-app notification even when ordinary notifications are disabled. Verify the data volume is selected correctly whenSCREENPIPE_DATA_DIRis a symlink, junction, or nested mount. -
large database (>10GB) — search still returns results within 2 seconds. app doesn't freeze on startup.
-
Snapshot compaction integrity — Verify compaction doesn't result in NULL offset_index or pool exhaustion. (
09245af5f) -
Audio chunk timestamps —
start_timeandend_timeare correctly set for reconciled and retranscribed audio chunks in the database. -
SCREENPIPE_DATA_DIR usage — Set the
SCREENPIPE_DATA_DIRenvironment variable. Verify the app uses this directory for all its data storage. (d5f30db71) -
DB pool starvation prevention — Simulate high database load (e.g., rapid screen activity, many pipes running) and monitor logs. Verify no "database is locked" errors or signs of DB pool starvation.
-
write stalls name their own cause — Run
screenpipe db compact(or any longVACUUM) while capture is active. Logs must say "another writer held the SQLite write lock", NOT "pool timed out"; the UI-event recorder must log this atwarn, noterror, so a routine VACUUM does not raise a Sentry issue. Starving the write pool instead must say "no write-pool connection became available". The two must never share a message. (SCREENPIPE-CLI-SQ) -
stuck write coordinator recovers — A process-wide SQLite write permit that is never released must not wedge writes forever. Verify a sustained contention run (past
CONTENTION_PERSISTENT_AFTER_WALL) marks the write path degraded and requests an engine restart, while a normal multi-minute maintenance hold does not. (SCREENPIPE-CLI-SQ) -
DB write coalescing queue — verify high-frequency captures (e.g. 10 FPS) don't lock the UI or cause write errors. (
c23768f41) -
Multi-byte window titles in suggestions — Interact with suggestions for windows that have multi-byte (e.g., Unicode, emoji) characters in their titles. Verify no char boundary panics.
-
no concurrent reconciliation issues — Verify that concurrent reconciliation processes do not cause issues during heavy load or sync operations. (
1d436bc3) -
pipe_config blobs skipped in sync — Verify that
pipe_configblobs are correctly skipped during synchronization, preventing unnecessary data transfer and potential issues. (08d5c53a) -
Pi's native auto-compaction for pipe session history — Verify that Pi's native auto-compaction feature for pipe session history works as expected, preventing indefinite growth of history and maintaining performance. (
8f49e2cf) -
UTF-8 panic with long multi-byte strings — Introduce long strings with multi-byte UTF-8 characters (e.g., in window titles, chat input, search queries). Verify no panics occur when these strings are truncated, stored, or processed.
-
fsync snapshots before DB commit — verify data integrity by force-quitting during heavy capture; snapshots should match DB entries. (
2e63282b8) -
Data directory setting location — Verify that the data directory setting is now located in the "Storage" tab of the settings menu. (
0d3ffe30a) -
store.bin encryption — Enable "Encrypt store.bin" in settings (Privacy > Security). Verify that
store.binis encrypted and correctly decrypted on startup using the OS keychain. (143875207,aee1cd2b5,85ecd7935) -
graceful keychain denial — On macOS, deny keychain access for store encryption. Verify the app handles it gracefully and falls back to unencrypted store if necessary or warns the user. (
b9c01b916) -
slow DB insert warning — check logs. "Slow DB batch insert" warnings should be <1s in normal operation. >3s indicates contention.
-
concurrent DB access — UI queries + recording inserts happening simultaneously. no "database is locked" errors.
-
store race condition — rapidly toggle settings while recording is active. no crash (
eea0c865). -
event listener race condition — Tauri event listener setup during rapid window creation. no crash (
cc09de61). -
UTF-8 boundary panic — search with special characters, non-ASCII text in OCR results. no panic on string slicing (
eea0c865). -
low disk space — with <1GB free, app should warn user. no crash from failed writes.
-
large database (>10GB) — search still returns results within 2 seconds. app doesn't freeze on startup.
-
Audio chunk timestamps —
start_timeandend_timeare correctly set for reconciled and retranscribed audio chunks in the database.
10. AI presets & settings
commits: 8a5f51dd, 0b0d8090, 7e58564e, 2522a7e2, f3e55dbc, 79f2913f
- Ollama not running — creating an Ollama preset shows free-text input fields (not stuck loading). user can type model name manually (
8a5f51dd). - custom provider preset — user can add a custom API endpoint. model name is free-text input with optional autocomplete.
- settings survive restart — change any setting, quit, relaunch. setting is preserved.
- overlay mode switch — change from fullscreen to window mode. setting saves. next shortcut press uses new mode.
- FPS setting — change capture FPS. recording interval changes accordingly.
- language/OCR engine setting — change OCR language. new language used on next capture cycle.
- video quality setting — low/balanced/high/max. affects FFmpeg encoding params (
21bddd0f). - Settings UI sentence case — All settings UI elements (billing, pipes, team) should use consistent sentence case.
- Sidebar text visibility in Auto theme — On macOS, switch between Light, Dark, and Auto system theme modes. Verify that sidebar text remains visible and legible in all modes. (
16d38570d) - Billing page links to website — Verify that the in-app billing page correctly links to the new website billing page.
- Non-pro subscriber Whisper fallback — As a non-pro subscriber, verify that audio transcription defaults to
whisper-large-v3-turbo-quantizedand functions correctly. - Pi restart on preset switch — Switch between different AI presets. Verify that the Pi agent restarts if required by the new preset.
- Web search disabled for non-cloud providers — When using a non-cloud AI provider, verify that web search functionality is correctly disabled.
- Credit balance in billing UI and errors — Verify that the billing UI accurately displays the credit balance and clearly differentiates between
credits_exhaustedand other LLM-related errors. - Unknown AI provider type sanitization — Configure a malformed or unknown AI provider type (e.g., by manual config edit). Verify the app doesn't crash on startup or when navigating to settings, and gracefully handles the unknown type.
- standalone settings page — Verify that clicking settings in the tray menu opens a standalone
/settingspage instead of a modal overlay. (ec2a5789e) - optional API auth — Enable API auth in settings (or via
--api-auth). Verify that remote access to the API requires the configured token. (09f18141a,cfc1a74e1) - privacy settings reordering — Verify that the Security section appears first in the Privacy settings tab. (
4718785b6) - password field filtering — Verify that password fields are skipped in the accessibility tree and not stored as OCR/text. (
8159641f5,d39e42e5b) - browser extension popup filtering — Verify that browser extension popups (like Bitwarden) are filtered and not captured in the accessibility tree or as black frames. (
52d20987a,449ae7a68,931db40b6)
commits: 8a5f51dd, 0b0d8090
- Ollama not running — creating an Ollama preset shows free-text input fields (not stuck loading). user can type model name manually (
8a5f51dd). - custom provider preset — user can add a custom API endpoint. model name is free-text input with optional autocomplete.
- settings survive restart — change any setting, quit, relaunch. setting is preserved.
- overlay mode switch — change from fullscreen to window mode. setting saves. next shortcut press uses new mode.
- FPS setting — change capture FPS. recording interval changes accordingly.
- language/OCR engine setting — change OCR language. new language used on next capture cycle.
- video quality setting — low/balanced/high/max. affects FFmpeg encoding params (
21bddd0f). - Settings UI sentence case — All settings UI elements (billing, pipes, team) should use consistent sentence case.
11. onboarding
commits: 87abb00d, 9464fdc9, 0f9e43aa, 7ea15f32, bf1f1004
- fresh install flow — onboarding appears, permissions requested, user completes setup.
- auto-advance after engine starts — status screen advances automatically after 15-20 seconds once engine is running (
87abb00d,9464fdc9). - skip onboarding — user can skip and get to main app. settings use defaults.
- Onboarding completion destination — After completing onboarding, verify that the home window opens instead of the timeline overlay. (
6ddc33a94,3cf668c76) - shortcut gate — onboarding teaches the shortcut. user must press it to proceed (
0f9e43aa). - onboarding window size — window is correctly sized, no overflow (
7ea15f32). - onboarding doesn't re-show — after completing onboarding, restart app. main window shows, not onboarding.
- First-run 2-hour reminder notification — On a fresh install, verify that a custom notification panel appears after approximately 2 hours as a first-run reminder.
commits: 87abb00d, 9464fdc9, 0f9e43aa, 7ea15f32
- fresh install flow — onboarding appears, permissions requested, user completes setup.
- auto-advance after engine starts — status screen advances automatically after 15-20 seconds once engine is running (
87abb00d,9464fdc9). - skip onboarding — user can skip and get to main app. settings use defaults.
- shortcut gate — onboarding teaches the shortcut. user must press it to proceed (
0f9e43aa). - onboarding window size — window is correctly sized, no overflow (
7ea15f32). - onboarding doesn't re-show — after completing onboarding, restart app. main window shows, not onboarding.
Desktop account login callbacks
- Windows consumer login, cold and running — sign in and sign up from a closed app and an already-running app. The
screenpipe://authcallback returns to the consumer build, stores the account, and never opens Timeline. - Windows Enterprise login, cold and running — repeat with the Enterprise build. The callback uses
screenpipe-enterprise://auth, reaches the Enterprise process, and never opens the consumer build or Timeline. - consumer and Enterprise both installed — start login from each build in turn. Each callback returns to the build that initiated it; a callback for the other registered scheme is rejected.
- onboarding versus existing account destination — an auth callback during incomplete setup returns to Onboarding and auto-advances after login; an auth callback from an established app returns to Home.
- wrong browser account retry — when the browser is already signed into the wrong account, sign out on the login page and sign in again. The original build scheme and callback version survive the Clerk round trip.
- blocked automatic protocol launch — block the browser's automatic custom-protocol launch, then use the visible "open screenpipe" fallback. The callback is delivered once to the correct build.
- default browser unavailable — make the OS browser launch fail and verify
open_login_windowfalls back to the isolated in-app WebView, including "use different account". - macOS and Linux parity — macOS ASWebAuthenticationSession and Linux system-browser login use the same versioned callback contract and return to the initiating build.
- CLI login remains separate —
/login?code=…&redirect=…completes the device-code flow without attempting a desktop custom-scheme callback.
12. timeline & search
commits: f1255eac, 25cbdc6b, 2529367d, d9821624, e61501da, 039d5fea, 50ff4f4c, 91cc4371, bcce42796, a98fa2991, 0ff93b167, adbbb8f84
- arrow key navigation — left/right arrow keys navigate timeline frames (
f1255eac). - search results sorted by time — search results appear in chronological order (
25cbdc6b). - no frame clearing during navigation — navigating timeline doesn't cause frames to disappear and reload (
2529367d). - URL detection in frames — URLs visible in screenshots are extracted and shown as clickable pills (
50ef52d1,aa992146). - app context popover — clicking app icon in timeline shows context (time, windows, urls, audio) (
be3ecffb). - Timeline single "current" bar — Verify that the timeline only shows one "current time" bar, even during rapid updates. (
bcce42796) - Timeline "Calls" filter — Verify the "Calls" filter on the timeline correctly filters for call-related events. (
0ff93b167) - Collapsible timeline filters — Verify that timeline filters can be collapsed and expanded correctly. (
0ff93b167) - window-focused refresh — opening app via shortcut/tray refreshes timeline data immediately (
0b057046). - code block colors in memories — Verify that code block colors in the memories page match the current app theme. (
1c8d785fc) - memories page pagination — Verify that memories page pagination works correctly and tags are loaded from the API. (
3e00b70b4) - frame deep link navigation —
screenpipe://frame/Norscreenpipe://frames/Nopens main window and jumps to frame N. works from cold start; invalid IDs show clear error. - missing frames return 404 — Attempt to access a non-existent frame via the API. Verify that it returns a 404 error. (
2e63282b8) - Search result exact navigation — Click a search result. Verify it navigates exactly to the associated
frame_id. (a98fa2991) - Search navigation persistence — Navigate to a frame from search results. Shift focus away from the app and back. Verify the navigation is not reset. (
71dee4ca3) - Search navigation race condition — Verify that search navigation works reliably even if the webview is still mounting (retries should handle it). (
2015137a1) - Consolidated text search — Perform keyword searches. Verify results are correctly pulled from the consolidated
frames.full_textandframes_fts. (adbbb8f84) - Keyword search accessibility — Keyword search should find content within accessibility-only frames and utilize
frames_ftsfor comprehensive accessibility text searching. - Keyword search logic — Verify that keyword search SQL correctly uses
ORinstead ofUNIONwithinIN(). - Search prompt accuracy — Verify that search prompts are improved to prevent false negatives from over-filtering.
- Past-day timeline navigation — Navigate the timeline to past days (e.g., using date picker or arrow keys). Verify that data loads correctly and the timeline behaves as expected.
-
content_type=allsearch and pagination — Perform search queries withcontent_type=all. Verify that the result count is accurate and pagination works correctly without missing or duplicating results. - Search pagination with offset — Perform paginated searches, particularly beyond the first page. Verify that results are not empty or incorrect due to double-applied offsets.
-
search_ocr()returns results for event-driven capture — Verify thatsearch_ocr()correctly returns OCR results for event-driven captures and does not return empty when visible text is present on screen. - timeline displays consistent timestamps — Verify that the timeline displays consistent timestamps, regardless of locale settings, and that there are no timestamp localization issues via websocket. (
2cf0c14e) - timeline retry backoff mechanism — Verify that the timeline's retry backoff mechanism functions as expected for data loading, ensuring resilience during temporary data unavailability. (
57cca740) - arrow key navigation between search results in timeline — Verify that left/right arrow keys correctly navigate between search results within the timeline view. (
3e8f37fc) - URL chips always shown when detected — Verify that URL chips are always displayed in the UI when URLs are detected in the content. (
cba69e56) - refresh button inline with suggestion chips (icon-only) — Verify that the refresh button for suggestion chips is displayed inline with the chips and is icon-only. (
a80e9ce6) - bottom suggestion chips hidden on empty chat — Verify that bottom suggestion chips are hidden when the chat is empty to avoid duplication. (
d6c4b821) - Refresh button for suggestion chips — A refresh button appears on bottom suggestion chips. Clicking it updates suggestions.
- Timeline refresh button hover — verify cursor-pointer and hover state on timeline refresh button. (
0cee47b62) - Smarter idle suggestions — Verify that "idle suggestions" appear and are contextually relevant when the user is inactive.
- Hide suggestion chips on empty chat — Verify that suggestion chips are hidden when the chat is empty to prevent duplication.
- Text selection not blocked by URL overlays — On URL-heavy pages, verify that text selection is not blocked by clickable URL overlays.
- AI suggestion chip refresh and animations — Verify a refresh button exists on AI suggestion chips, and appropriate animations (e.g., loading spinner) are shown when refreshing.
- Activity summary time measurement and relative parsing — Verify activity summaries display accurate time measurements and relative time parsing (e.g., "5 minutes ago", "yesterday") works correctly in the UI.
- Hybrid OCR for canvas apps — Verify that text from Google Docs and Figma (canvas-rendered) is captured using hybrid OCR. (
4d2b05990,f09f1e9aa) - Search modal scroll — Verify that the search modal is scrollable on Windows/Linux embedded timeline and trackpad/wheel scrolling works. (
f108f1f0d,2a2bd9b5,5762c60bf) - Modal scrolling (general) — Verify that all modals (e.g., settings, pipes, search) are scrollable and handle overflow correctly, especially on Windows and Linux. (
19789657d) - Search modal UX — Verify that click interference from Live Text and wheel handlers is resolved, and app/date filter timezone bugs are fixed. (
0c883819e,b7123231,f09f1e9aa) - Timeline filter viewport scoping — verify timeline filters apply to current viewport, not a fixed 800-frame window. (
9277431e4) - Chat UI code blocks — verify light text on dark bg in chat code blocks. (
c029f7779) - Chat image viewer — verify images can be viewed in chat. (
2bcdf8d8b) - Chat preset dropdown — verify AI preset switching within chat. (
2bcdf8d8b) - Memories Settings UI — verify frame_id relationship and Memories settings work as expected. (
67f4c4304)
commits: f1255eac, 25cbdc6b, 2529367d, d9821624
- arrow key navigation — left/right arrow keys navigate timeline frames (
f1255eac). - search results sorted by time — search results appear in chronological order (
25cbdc6b). - no frame clearing during navigation — navigating timeline doesn't cause frames to disappear and reload (
2529367d). - URL detection in frames — URLs visible in screenshots are extracted and shown as clickable pills (
50ef52d1,aa992146). - app context popover — clicking app icon in timeline shows context (time, windows, urls, audio) (
be3ecffb). - window-focused refresh — opening app via shortcut/tray refreshes timeline data immediately (
0b057046). - frame deep link navigation —
screenpipe://frame/Norscreenpipe://frames/Nopens main window and jumps to frame N. works from cold start; invalid IDs show clear error. - Keyword search accessibility — Keyword search should find content within accessibility-only frames and utilize
frames_ftsfor comprehensive accessibility text searching. - Keyword search logic — Verify that keyword search SQL correctly uses
ORinstead ofUNIONwithinIN(). - Search prompt accuracy — Verify that search prompts are improved to prevent false negatives from over-filtering.
13. sync & cloud
- CLI remote sync — Run
screenpipe sync remote. Verify it correctly syncs data to a remote SSH/SFTP server. (f46e85cb1)
commits: 2f6b2af5, ea7f1f61, 5cb100ea
- auto-remember sync password — user doesn't have to re-enter password each time (
5cb100ea). - auto-download from other devices — after upload cycle, download new data from paired devices (
2f6b2af5). - auto-init doesn't loop — sync initialization happens once, doesn't repeat endlessly (
ea7f1f61). - Cloud archive docs — Verify that the cloud archive documentation page exists and is accessible via a link from settings.
- simplified Arc URL extraction — Verify that simplified Arc URL extraction works correctly, capturing URLs from Arc browser content. (
08d5c53a) - Randomly generated cloud sync password — On new sync setup, verify that a randomly generated cloud sync password is used.
- Trialing subscriptions for pipe sync — With a trialing subscription, verify that pipe sync functions as if the subscription is active, and pipes sync correctly.
- Encrypted pipe sync (Pro) and locked toggle (non-Pro) — As a Pro user, enable encrypted pipe sync and verify pipes sync encrypted. As a non-Pro user, verify the encrypted pipe sync toggle is locked and inaccessible.
- Arc URL extraction and pipe_config blobs — If Arc Browser is supported, verify accurate URL extraction. Verify that
pipe_configblobs are correctly skipped during sync (requires inspection of sync data or logs). - Per-device record counts in sync — In sync settings, verify that record counts are displayed for each synchronized device and that sync configuration persists across restarts. (
0e7baaedb) - transcription daily cost cap — Verify that the daily cost cap for transcription is correctly enforced and prevents further transcription once reached. (
2f67a1041) - local Google Calendar OAuth — Connect Google Calendar. Verify it uses the local OAuth flow instead of a cloud-based one. (
0177fdf2b)
14. Region OCR (Shift+Drag)
commits: b3628788, 738178da
- Shift+Drag region OCR functionality — Perform a
Shift+Dragregion OCR selection on the screen. Verify that the RegionOcrOverlay appears correctly and local OCR processes the selected region. - Local OCR without login for Shift+Drag — Verify that the
Shift+Dragregion OCR uses local OCR and functions correctly without requiring the user to be logged in or have a cloud subscription.
15. Windows-specific
commits: eea0c865, fe9060db, c99c3967, aeaa446b, 5a219688, caae1ebc, 67caf1d1, ff4af7b5
- pre-AVX / non-AVX2 CPU launch (compatibility mode) — (#3125) On x86-64 CPUs without AVX (Atom-line Celeron/Pentium such as the N5095 = Jasper Lake/Tremont, pre-2011 Intel, QEMU
-cpu qemu64), the app and CLI must LAUNCH and RECORD instead of dying with0xC000001D STATUS_ILLEGAL_INSTRUCTION. Test on a NO-AVX CPU, not merely a no-AVX2 one: measured on real Windows guests, the pre-fix build ranrecordfor 420s under an emulated Sandy Bridge (which has AVX) and died in 1.4s under Westmere (no AVX) withException code: 0xc000001d, faulting modulescreenpipe.exe./arch:AVX2codegen emits VEX-encoded AVX instructions, so a Sandy-Bridge-class probe passes builds that crash in the field. Local whisper/qwen3 STT is disabled at runtime (AVX2-compiled kernels); parakeet + cloud engines keep working; onboarding shows a "compatibility mode" notice. Guards: never set globalCFLAGS/CXXFLAGS=/arch:AVX2in Windows release workflows (it poisons every cc/cmake dep incl. bundled SQLite → crash in static initializers before main); ONNX Runtime must stay on the MS DirectML DLL (import-table link, runtime CPUID dispatch) — pyke'sdownload-binariesstatic libs are AVX2-only. CI:release-cli.yml'ssmoke-windowsjob (runs-on windows-latest — SDE's Pin injector is broken on windows-2022, and every SDE 10.x kit fails injection on current hosted images; 9.58 works) runs the packaged exe AND an ONNX-init probe (.github/ci/ort-smoke, realSession::builder()against the shipped DirectML DLL) under Intel SDE-wsm -chip_check_exe_onlyon every Windows CLI build, andrelease/publish-npmrequire it;release-app.ymlprobes the app exe natively via the hidden--cpu-smokeflag (static init + import table).-chip_check_exe_onlyis what makes pre-AVX emulation usable — it scopes the chip check to the main image so the host's own AVX-executing system DLLs can't cause false failures. Reproduce locally withsde -wsm -chip_check_exe_only -- screenpipe.exe --version(pre-fix build faults onvpxor; fixed build prints its version), or QEMU-cpu Westmere/-cpu qemu64for a full guest. Pipes/AI chat on such CPUs use bun's officialwindows-x64-baselinebuild (runtime-downloaded, mandatory SHA-256; verified 2026-07-31 to run undersde -snbwhile stock bun faults). - COM thread conflict — audio and vision threads don't conflict on COM initialization (
eea0c865). - high-DPI display (150%, 200%) — OCR captures at correct resolution.
- multiple monitors — all detected and recorded.
- Windows Defender — app not blocked by default security.
- Windows default mode — On Windows, the app should default to window mode on first launch.
- Windows taskbar icon — The app should display a taskbar icon on Windows.
- Enterprise enforced auto-start enrollment — In an installed Windows enterprise build, set
lockedSettings.autoStartEnabled = "true", disable Screenpipe in Task Manager Startup apps, and verify both the HKCURuncommand (including--autostart) andStartupApproved\Runreturn to enabled within two seconds. Sign out/in and confirm Screenpipe starts in the background. Remove the policy, disable startup again, wait at least two reconciliation intervals, and verify it remains disabled. - Windows login window resets stale OAuth navigation — Click login, choose GitHub or Google, leave the provider flow open, then click login in Screenpipe again. The existing "sign in to screenpipe" window must return to the Screenpipe login page instead of showing the stale provider page or a blank document.
- Windows audio transcription accuracy — On Windows, verify improved audio transcription accuracy due to native Silero VAD frame size and lower speech threshold.
- Windows multi-line pipe prompts — Multi-line pipe prompts should be preserved on Windows.
- Windows ARM64 support — On a Windows ARM64 device, verify the app installs and runs correctly. (
d62360bc4) - Windows app matching for meetings — On Windows, verify that meeting detection correctly matches active applications. (
ef39e728d) - Alt+S shortcut activates overlay with keyboard focus — On Windows, press
Alt+S. Verify that the overlay window appears and immediately receives keyboard focus, allowing immediate typing. - OcrTextBlock deserialization handles Windows OCR format — On Windows, verify that
OcrTextBlockdeserialization correctly handles the specific Windows OCR format. (c49ccb55) - populate accessibility tree bounds for text overlay on Windows — On Windows, verify that accessibility tree bounds are correctly populated for text overlay, ensuring accurate positioning and interaction. (
4d20803a) - capture full accessibility tree for Chromium/Electron apps on Windows — On Windows, verify that the full accessibility tree is captured for Chromium/Electron applications. (
2e50c772) - Accessibility tree bounds for text overlay — On Windows, verify that text overlays accurately reflect the accessibility tree bounds, making selection and interaction precise.
- No console flash during GPU detection — On Windows startup, verify that no temporary console window flashes during the GPU detection process. (
a0aba1643) - Filter noisy system apps — On Windows, verify that noisy system apps are filtered out from screen capture and do not appear in the timeline or search results.
- Settings window instead of overlay — On Windows, verify that the Settings window is used instead of the overlay for settings, and the shortcut toggle works correctly. (
c13e21b55) - background work is deprioritized on Windows; app process and UI stay at Normal — (#4849) CLI
screenpipe recorddrops itself to BELOW_NORMAL_PRIORITY_CLASS (verify(Get-Process screenpipe).PriorityClass→BelowNormal, CI asserts inwindows-integration-test.yml; opt-outSCREENPIPE_KEEP_NORMAL_PRIORITY=1). The desktop app process must stayNormal— it gets targeted lowering only: audio-encode ffmpeg children spawnBelowNormal, compaction ffmpeg staysIdle, pipe/agent bun subtree spawnsBelowNormal(interactive chat's pi sidecar staysNormal— separate spawner in src-tauri/pi.rs), whisper inference dips its thread per-call, LL input-hook threads pinned HIGHEST (system-wide input path — Windows silently unhooks starved LL hooks). Verify children:Get-CimInstance Win32_Process -Filter "Name='ffmpeg.exe' OR Name='bun.exe'"+(Get-Process -Id …).PriorityClasswhile recording with a pipe enabled. If audio capture gaps appear under all-core CPU load in the CLI, see #4916 (cpal fork's broken thread-priority boost — capture threads not insulated from the class drop). - foreground apps stay responsive while a11y capture runs (UIA tree walks off by default) — Full-window UIA tree walks are synchronous cross-process calls serviced on the target app's UI thread. The old 2s periodic + focus-change walks caused p95 213ms message-pump stalls (~97 freezes >100ms per 2 min) in Edge and were ~100% of severe foreground freezes; their snapshots also had zero consumers (
paired_capture.rsowns a11y text capture).capture_tree/tree_capture_interval_msnow default tofalse/0(crates/screenpipe-a11y/src/config.rs), including the startup walk. Preserved: per-clickElementFromPointenrichment and a debounced single-element focused-element refresh on focus change (feeds click/app_switch/window_focus element context). Verify: (a)scripts/windows/cpu-investigation/walker-fix-verification/verify-walker-fix.ps1(self-contained before/after harness with PASS/FAIL gate; measured p95 156ms → 1.6ms, stalls>100ms 108 → 4 per 2min) or the raw probescripts/windows/cpu-investigation/experiments/measure-ui-latency.ps1; (b)ui_eventsrows still carryelementcontext for clicks and app switches (cargo run -p screenpipe-a11y --example windows_probe_harness); (c) anyone re-enablingcapture_treemust keep the startup walk gated on it.
commits: eea0c865, fe9060db, c99c3967, aeaa446b, 5a219688, caae1ebc, 67caf1d1
- COM thread conflict — audio and vision threads don't conflict on COM initialization (
eea0c865). - high-DPI display (150%, 200%) — OCR captures at correct resolution.
- multiple monitors — all detected and recorded.
- Windows Defender — app not blocked by default security.
- Windows default mode — On Windows, the app should default to window mode on first launch.
- Windows taskbar icon — The app should display a taskbar icon on Windows.
- Windows audio transcription accuracy — On Windows, verify improved audio transcription accuracy due to native Silero VAD frame size and lower speech threshold.
- Windows multi-line pipe prompts — Multi-line pipe prompts should be preserved on Windows.
Windows text extraction matrix (accessibility vs OCR)
The event-driven pipeline (paired_capture.rs) decides per-frame whether to use accessibility tree text or OCR. Terminal apps force OCR because their accessibility tree only returns window chrome.
commits: 5a219688 (wire up Windows OCR), caae1ebc (prefer OCR for terminals), 67caf1d1 (no chrome fallback)
App categories and expected behavior:
| App category | Examples | app_prefers_ocr | Text source | Expected text |
|---|---|---|---|---|
| Browser | Chrome, Edge, Firefox | false | Accessibility | Full page content + chrome |
| Code editor | VS Code, Fleet | false | Accessibility | Editor content, tabs, sidebar |
| Terminal (listed) | WezTerm, Windows Terminal, Alacritty | true | Windows OCR | Terminal buffer content via screenshot |
| Terminal (unlisted) | cmd.exe, powershell.exe | false | Accessibility | Whatever UIA exposes (may be limited) |
| System UI | Explorer, taskbar, Settings | false | Accessibility | UI labels, text fields |
| Games / low-a11y apps | Games, Electron w/o a11y | false | Windows OCR (fallback) | OCR from screenshot |
| Lock screen | LockApp.exe | false | Accessibility | Time, date, battery |
Terminal detection list (app_prefers_ocr matches, case-insensitive):
wezterm, iterm, terminal, alacritty, kitty, hyper, warp, ghostty
Note: "terminal" matches WindowsTerminal.exe but NOT cmd.exe or powershell.exe.
Test checklist:
- WezTerm OCR capture — open WezTerm, type commands. search for terminal content within 30s. should return OCR text, NOT "System Minimize Restore Close" chrome.
- Windows Terminal OCR — same test with Windows Terminal.
- Chrome/Edge full accessibility — open Chrome or Edge, browse a page. search returns full page content from accessibility tree, not just limited UI elements.
- VS Code full accessibility — open VS Code with a file. search returns full code content and UI elements from accessibility tree.
- Game/no-a11y OCR fallback — open an app with poor accessibility. OCR should run and extract text from screenshot.
- OCR engine name — query DB: OCR entries should have engine
WindowsNative(notAppleNative). - Failed OCR = no noise — if OCR fails for a terminal, the frame should have NULL text, not chrome like "System Minimize Restore Close".
- Non-terminal chrome-only — rare case where a normal app returns only chrome from accessibility. stored as-is (acceptable, no OCR fallback triggered).
- Empty accessibility + empty OCR — app with no tree text and OCR failure. frame stored with NULL text. no crash.
- OCR text persisted on frames —
SELECT COUNT(*) FROM frames WHERE full_text IS NOT NULL AND full_text != ''should be non-zero after a few minutes of use on Windows. (Theocr_texttable was retired; OCR text now lives inframes.full_text, per-word boxes inframes.text_json.)
Windows text extraction — untested / unknown apps
These apps are common on Windows but have never been tested with the event-driven pipeline. We don't know if their accessibility tree returns useful text or just chrome. Each needs manual verification: open the app, use it for a few minutes, then curl "http://localhost:3030/search?app_name=<name>&limit=3" and check if the text is meaningful.
Status legend: ? = untested, OK = verified good, CHROME = only returns chrome, EMPTY = no text, OCR-NEEDED = should be added to app_prefers_ocr
| App | Status | a11y text quality | Notes |
|---|---|---|---|
| Browsers | |||
| Chrome | OK | good (full page content) | 2778ch avg, rich a11y tree |
| Edge | ? | probably good | same Chromium UIA as Chrome |
| Firefox | ? | unknown | different a11y engine than Chromium |
| Brave / Vivaldi / Arc | ? | probably good | Chromium-based, needs verification |
| Code editors | |||
| VS Code | ? | unknown | Electron, should have good UIA |
| JetBrains (IntelliJ, etc) | ? | unknown | Java Swing/AWT, UIA quality varies |
| Sublime Text | ? | unknown | custom UI, may need OCR fallback |
| Cursor | ? | unknown | Electron fork of VS Code |
| Zed | ? | unknown | custom GPU renderer, a11y unknown |
| Terminals | |||
| WezTerm | CHROME | chrome only ("System Minimize...") | app_prefers_ocr = true, OCR works |
| Windows Terminal | ? | unknown | matches "terminal" in app_prefers_ocr |
| cmd.exe | ? | unknown | NOT matched by app_prefers_ocr |
| powershell.exe | ? | unknown | NOT matched by app_prefers_ocr |
| Git Bash (mintty) | ? | unknown | NOT matched by app_prefers_ocr |
| Communication | |||
| Discord | ? | unknown | Electron, old OCR data exists |
| Slack | ? | unknown | Electron |
| Teams | ? | unknown | Electron/WebView2 |
| Zoom | ? | unknown | custom UI |
| Telegram | ? | unknown | Qt-based |
| ? | unknown | Electron | |
| Productivity | |||
| Notion | ? | unknown | Electron |
| Obsidian | ? | unknown | Electron |
| Word / Excel / PowerPoint | ? | unknown | native Win32, historically good UIA |
| Outlook | ? | unknown | mixed native/web |
| OneNote | ? | unknown | UWP, should have good UIA |
| Media / Creative | |||
| Figma | ? | unknown | Electron + canvas, likely poor a11y on canvas |
| Spotify | ? | unknown | Electron/CEF |
| VLC | ? | unknown | Qt-based |
| Adobe apps (Photoshop, etc) | ? | unknown | custom UI, historically poor a11y |
| System / Utilities | |||
| Explorer | OK | good | file names, paths, status bar |
| Settings | ? | unknown | UWP, should be good |
| Task Manager | ? | unknown | UWP on Win11 |
| Notepad | ? | unknown | should have excellent UIA |
| Games / GPU-rendered | |||
| Any game | ? | likely empty | GPU-rendered, no UIA tree. should fall to OCR |
| Electron w/ disabled a11y | ? | likely empty | some Electron apps disable a11y |
Priority to test (most common user apps):
- VS Code — most developers will have this open
- Discord / Slack — always running in background
- Windows Terminal / cmd.exe / powershell.exe — verify terminal detection
- Edge / Firefox — browser is primary use
- Notion / Obsidian — knowledge workers
- Office apps — enterprise users
How to verify an app:
# 1. Open the app, use it for 2 minutes
# 2. Check what was captured:
curl "http://localhost:3030/search?app_name=<exe_name>&limit=3&content_type=all"
# 3. If text is only chrome (System/Minimize/Close), it may need adding to app_prefers_ocr
# 4. If text is empty and screenshots exist, OCR fallback should kick in
# 5. Update this table with findings
Apps that may need adding to app_prefers_ocr list:
- If cmd.exe / powershell.exe return chrome-only text, add
"cmd"and"powershell"to the list - If mintty (Git Bash) returns chrome-only, add
"mintty" - Any app where the accessibility tree consistently returns only window chrome but screenshots contain readable text
15. Help and Support
commits: deac5ea9
- Intercom integration in help section — Navigate to the desktop app's help section. Verify that Crisp is replaced by Intercom and that the Intercom chat widget and knowledge base search function as expected.
16. CI / release
commits: 8f334c0a, fda40d2c
- macOS 26 runner — release builds on self-hosted macOS 26 runner (
fda40d2c). - updater artifacts — release includes
.tar.gz+.sigfor macOS,.nsis.zip+.sigfor Windows. - prod config used — CI copies
tauri.prod.conf.jsontotauri.conf.jsonbefore building. identifier isscreenpi.penotscreenpi.pe.dev. - draft then publish —
workflow_dispatchcreates draft. manual publish orrelease-app-publishcommit publishes. - macOS E2E workflow — Verify the macOS E2E workflow in CI ensures stability across releases. (
18ca34d55)
16. MCP / Claude integration
commits: 8c8c445c
- Claude connect button works — Settings → Connections → "Connect Claude" downloads
.mcpbfile and opens it in Claude Desktop. was broken because GitHub releases API pagination didn't reachmcp-v*releases buried behind 30+ app releases (8c8c445c). - MCP release discovery with many app releases —
getLatestMcpRelease()paginates up to 5 pages (250 releases) to findmcp-v*tagged releases. verify it works even when >30 app releases exist since last MCP release. - Claude Desktop not installed — clicking connect shows a useful error, not a silent failure.
- MCP version display — Settings shows the available MCP version and whether it's already installed.
- macOS Claude install flow — downloads
.mcpb, opens Claude Desktop, waits 1.5s, then opens the.mcpbfile to trigger Claude's install modal. - Windows Claude install flow — same flow using
cmd /c startinstead ofopen -a. - download error logging — if download fails, console shows actual error message (not
{}).
17. AI Agents / Pipes
commits: fa887407, 815f52e6, 60840155, e66c3ff8, c905ffbf, 01147096, 5908d7f4, 46422869, 4f43da70, 71a1a537, 6abaaa36, f3e55dbc, 8e426dec, 1289f51e, 4bc9ff1a, c336f73d, 2f7416ae
- Pi process stability — After app launch,
ps aux | grep pishould show a single, stablepiprocess that doesn't restart or get killed. - Pi readiness handshake — First chat interaction with Pi should be fast (<2s for readiness).
- Pi auto-recovery — If the
piprocess is manually killed, it should restart automatically within a few seconds and be ready for chat. - Pipe output accuracy — When executing a pipe, the user's prompt should be accurately reflected in the output.
- Silent LLM errors — LLM errors during pipe execution should be displayed to the user, not silently suppressed.
- Fast first chat with Pi — The first interaction with Pi after app launch should be responsive, with no noticeable delay (aim for <2s).
- Activity Summary tool — MCP can access activity summaries via the
activity-summarytool, and theactivity-summaryendpoint works correctly. - Search Elements tool — MCP can search elements using the
search-elementstool. - Frame Context tool — MCP can access frame context via the
frame-contexttool. - Progressive disclosure for AI data — AI data querying should progressively disclose information.
- Screenpipe Analytics skill — The
screenpipe-analyticsskill can be used by the Pi agent to perform raw SQL usage analytics. - Screenpipe Retranscribe skill — The
screenpipe-retranscribeskill can be used by the Pi agent for retranscription. - AI preset save stability — Saving AI presets should not cause crashes, especially when dealing with pipe session conflicts.
- Pipe token handling — Ensure that Pi configuration for pipes uses the actual token value, not the environment variable name.
- Pipe user_token passthrough — Verify that the
user_tokenis correctly passed to Pi pre-configuration so pipes use the screenpipe provider. - Pipe preset override — Install a pipe from the store. Verify its preset can be overridden by user's default. (
bee49f1e7) - Pipe configurable timeout — Add
timeoutto pipe.md frontmatter. Verify pipe respects this timeout. (cc0ecef53) - Pipe store caching — Navigate pipe store and connections pages. Verify fast loading due to client-side caching. (
f501c19fb) - Primary + fallback AI preset UI — Verify the UI for primary and fallback AI presets for pipes works as expected. (
da206471a) - Default AI model ID — Verify that the default AI model ID does not contain outdated date suffixes.
- Move provider/model flags —
--providerand--modelflags should be correctly moved before-p promptinpi spawncommands. - Pi restart on preset switch — Switch between different AI presets. Verify that the Pi agent restarts if required by the new preset.
- Faster Pipes page loading — Verify that the "Pipes" page loads significantly faster, especially when there are a large number of pipes configured.
- Instant pipe enable toggle UI update — Toggle a pipe's enable status. Verify that the UI updates instantly due to optimistic updates, even if the backend operation takes a moment.
- Pipe execution shows parsed text — Execute a pipe that outputs JSON. Verify that the output displayed to the user is correctly parsed text, not raw JSON.
- Surface LLM errors in chat UI — Interact with the chat UI using an AI provider under conditions that would cause LLM errors (e.g., exhausted credits, rate limits). Verify these errors are clearly surfaced to the user.
- Pipe preset bug fixes and credit drain prevention — Thoroughly test creating, editing, and switching pipe presets to ensure no bugs, especially those that might lead to unexpected cloud credit usage or misconfiguration.
- pipe UI improvements — Verify the overall improvements to the Pipes UI, ensuring a better user experience. (
2e68400c) - proper spinner icon for pipe refresh button — Verify that the pipe refresh button displays the correct spinner icon during loading states. (
b709af2f) - ChatGPT OAuth provider in pipes — Configure ChatGPT OAuth provider. Verify that pipes using ChatGPT work correctly.
- Reduced excessive Pi restarts — When changing AI preset values or other settings, verify that excessive Pi restarts are reduced. Monitor logs for unnecessary restart messages.
- Invalid UTF-8 in Pi streaming — Execute a pipe that outputs invalid UTF-8 characters to stdout/stderr. Verify that Pi streaming correctly handles these without crashing or displaying garbled output.
- Auto-abort stuck Pi agent — Verify that the Pi agent is auto-aborted if stuck before sending a new message. (
602419151) - Pi crash loop fix (Windows) — Verify that the Pi agent doesn't enter a crash loop on Windows due to lru-cache interop issues. (
de56176e5) - Token counter — Verify that the chat UI displays a token counter. (
2f75e90bf) - Optimize button — Verify that the "optimize" button appears in the pipe dropdown menu. (
5dff9d21a) - Pipes as App Store — Verify the redesigned Pipes tab, which provides a unified app store experience. (
89d2e0129) - Tool call UI with progress rail — Execute a pipe that uses tool calls. Verify the redesigned UI featuring a progress rail timeline and auto-collapse for friendly interaction. (
6c23e1399,d81ea65c1) - In-app Notification Panel — Use the
/notifyAPI (e.g., via a pipe). Verify an in-app notification panel appears instead of a system notification. (34937b2dc) - Pipe store stability — verify null guards, sharp corners, unpublish functionality, and data unwrap fixes. (
603c84f7b) - Pi agent & search timeouts — Run a long-running search or Pi agent task. Verify it doesn't timeout prematurely at 60s (should allow up to 120s for search). (
f01213cf5) - allow schedule + triggers together in pipe config UI — Verify that both schedule and triggers can be configured together in the pipe config UI without conflicts. (
f32bf9230) - local event triggers for pipes — Verify that pipes can be triggered by local events such as meeting start/end and pipe chaining. (
508b68ff7,776587aa7) - one event-triggered run per meeting-end generation — With meeting-summary enabled, join a call, leave, rejoin the same app within 120s (this reopens the same meeting row), then leave again. Duplicate delivery of either persisted end timestamp must be suppressed, but the final end after resume must create a second execution for the same meeting id so it summarizes the full transcript. Retranscribing saved audio must create one additional generation only when replacement segments were committed. verify:
grep "suppressed duplicate 'meeting_ended'" ~/.screenpipe/screenpipe-app.*.logandsqlite3 ~/.screenpipe/db.sqlite "SELECT event_key FROM pipe_event_runs WHERE pipe_name='meeting-summary' AND event_name='meeting_ended' ORDER BY claimed_at"shows distinct<meeting-id>@<generation>keys;sqlite3 ~/.screenpipe/db.sqlite "SELECT id, trigger_event, trigger_key FROM pipe_executions WHERE pipe_name='meeting-summary' ORDER BY id DESC LIMIT 5"keeps the user-facingtrigger_keyequal to the meeting id. (#5481) - failed event run retries — Force an event-triggered run to fail (e.g. sign out of the preset's provider mid-run). Its claim must be released so the next delivery of that event runs. verify:
sqlite3 ~/.screenpipe/db.sqlite "SELECT * FROM pipe_event_runs"no longer holds the failed key. (#5481) - tool call indicators in pipe run output — Verify that tool call indicators are displayed in the pipe run output. (
dda33a6a7) - align copy and chat icons in pipe run history — Verify that copy and chat icons are properly aligned in the pipe run history. (
f8fe5cff4) - Live pipe output streaming — Open the "Runs" tab for a running pipe. Verify that the output streams live as the pipe executes. (
4c1fab276) - Rich activity-summary — Verify that activity summaries include details about windows, URLs, and audio transcriptions. (
f2d8ba1dad3) - OpenAI-compatible transcription endpoint — Verify that the
/v1/audio/transcriptionsendpoint works correctly with standard OpenAI clients. (59deeba19) - Mermaid diagram XSS sanitization — Verify that mermaid diagrams in the UI are correctly sanitized to prevent XSS attacks. (
3405e9793) - Per-machine pipe favorites (stars) — Toggle the star icon for a pipe. Verify that favorites are persisted per-machine and that the filter chip correctly shows starred pipes first. (
e1a18adb9,0a2c1abb7) - Connected integrations @mentions in chat — Open the filter popover in chat. Verify that connected integrations (like Notion, Slack, Google Docs) appear as @mentions for easy filtering. (
1c0c95b20)
commits: fa887407, 815f52e6, 60840155, e66c3ff8, c905ffbf, 01147096, 5908d7f4, 46422869, 4f43da70, 71a1a537, 6abaaa36
- Pi process stability — After app launch,
ps aux | grep pishould show a single, stablepiprocess that doesn't restart or get killed. - Pi readiness handshake — First chat interaction with Pi should be fast (<2s for readiness).
- Pi auto-recovery — If the
piprocess is manually killed, it should restart automatically within a few seconds and be ready for chat. - Pipe output accuracy — When executing a pipe, the user's prompt should be accurately reflected in the output.
- Silent LLM errors — LLM errors during pipe execution should be displayed to the user, not silently suppressed.
- Fast first chat with Pi — The first interaction with Pi after app launch should be responsive, with no noticeable delay (aim for <2s).
- Activity Summary tool — MCP can access activity summaries via the
activity-summarytool, and theactivity-summaryendpoint works correctly. - Search Elements tool — MCP can search elements using the
search-elementstool. - Frame Context tool — MCP can access frame context via the
frame-contexttool. - Progressive disclosure for AI data — AI data querying should progressively disclose information.
- Screenpipe Analytics skill — The
screenpipe-analyticsskill can be used by the Pi agent to perform raw SQL usage analytics. - Screenpipe Retranscribe skill — The
screenpipe-retranscribeskill can be used by the Pi agent for retranscription. - AI preset save stability — Saving AI presets should not cause crashes, especially when dealing with pipe session conflicts.
- Pipe token handling — Ensure that Pi configuration for pipes uses the actual token value, not the environment variable name.
- Pipe user_token passthrough — Verify that the
user_tokenis correctly passed to Pi pre-configuration so pipes use the screenpipe provider. - Default AI model ID — Verify that the default AI model ID does not contain outdated date suffixes.
- Move provider/model flags —
--providerand--modelflags should be correctly moved before-p promptinpi spawncommands.
18. Admin / Team features
commits: 58460e02, 853e0975
- Admin team-shared filters — Admins should be able to remove individual team-shared filters.
- Simplified team invite — Verify the simplified team invite flow using a single web URL without requiring a passphrase. (
44a19b73f,b53b08b6e) - Per-request AI cost tracking and admin spend endpoint — Verify that per-request AI costs are tracked correctly and that the admin spend endpoint provides accurate usage data.
commits: 58460e02
- Admin team-shared filters — Admins should be able to remove individual team-shared filters.
19. Logging
commits: fc830b43, f54d3e0d
- Reduced log noise — Verify a significant reduction in log noise (~54%).
- PII scrubbing — Ensure that PII (Personally Identifiable Information) is scrubbed from logs.
- Phone regex PII scrubbing preservation — Verify phone numbers are scrubbed but accessibility bounds (which look like numbers) are NOT mangled. (
08feb4df5) - Phone regex PII scrubbing — After generating some PII-containing data (e.g., typing phone numbers), review logs to ensure that the phone regex correctly scrubs PII and does not over-match bare digit sequences.
20. Vault Lock (Encryption at rest)
commits: 274a968af, dc575e48e, 81aabbf18, d5e071854, db08f8c06, f4225b580
- Vault lock initialization — Verify that the vault can be initialized and a password set.
- Encryption of database and data files — Verify that screenpipe data is encrypted at rest when the vault is locked.
- Recording stop on lock — Verify that recording stops immediately when the vault is locked.
- Recording resume on unlock — Verify that recording restarts automatically when the vault is unlocked.
- Fast vault unlock — Verify that the DB is decrypted quickly and data files are decrypted in the background. (
dc575e48e) - Vault lock shortcut — Verify that the configurable vault lock shortcut works as expected. (
81aabbf18) - CLI vault commands — Verify that
screenpipe vaultcommands work without the server running. (f4225b580) - Skip server start on locked vault — Verify that the server does not start if the vault is locked. (
d5e071854)
21. Privacy & Incognito Detection
- PII Filter — Toggle the PII filter in chat or search. Verify that sensitive information is filtered using Tinfoil. (
fec0f1023)
commits: ad431b513, d9722bccc, 4df21e83d
- Incognito window detection — Verify that private browsing/incognito windows are correctly detected for major browsers (Chrome, Safari, Firefox, etc.). (
ad431b513) - Ignore incognito toggle — Verify that the "Ignore Incognito Windows" toggle in settings correctly prevents recording of private windows. (
d9722bccc) - Incognito detection UI feedback — Verify that the UI correctly reflects when an incognito window is being ignored.
- DRM pause behavior — Play DRM-protected content (e.g., Netflix in Safari). Verify that Screenpipe pauses recording gracefully and resumes automatically once the DRM content is closed, without crashing the server. (
3d9f0e8bb) - LAN-access toggle — Toggle "Enable LAN access" in API settings. Verify that the API binds to
0.0.0.0and thatapi_authis forcibly enabled for security. (c8d9c83f0)
commits: fc830b43
- Reduced log noise — Verify a significant reduction in log noise (~54%).
- PII scrubbing — Ensure that PII (Personally Identifiable Information) is scrubbed from logs.
23. GPU & Performance Telemetry
- GPU error handling & telemetry — Verify that GPU errors are handled gracefully and CPU/GPU telemetry is correctly reported in logs. (
0d42ea221) - Clipboard thread leak — Verify that long-running sessions do not exhibit gradual input lag or memory growth due to clipboard thread leaks. (
0718c2e03,f0adcddd0)
24. Data Management
- Delete local data confirmation — Use the "Delete device local data" feature. Verify an
AlertDialogappears instead of a standardwindow.confirm. (b5db080d6)
25. Feedback & Support
- Compressed feedback screenshots — Send feedback with a screenshot. Verify that the screenshot is compressed to JPEG before sending. (
591710246)
how to run
before every release
- run sections 1-4 completely (90% of regressions)
- spot-check sections 5-10
before merging window/tray/dock changes
run section 1 and 2 completely. these are the most fragile.
before merging vision/OCR changes
run section 3, 5, and 14 (Windows text extraction matrix) completely.
before merging audio changes
run section 4 completely.
before merging AI changes
run section 10.
before merging updater / tray-update changes
run section 32, and run bun run test:e2e:packaged-updater:macos (macOS).
known limitations (not bugs)
- tray icon on notched MacBooks can end up behind the notch if menu bar is crowded. Cmd+drag to reposition. dock menu is the fallback.
- macOS only shows permission prompts once (NotDetermined → Denied is permanent). must use System Settings to re-grant.
- debug builds use ~3-5x more CPU than release builds for vision pipeline.
- first frame after app launch always triggers OCR (intentional — no previous frame to compare against).
- chat panel is pre-created hidden at startup so it exists before user presses the shortcut. Creation no longer activates/shows — only the show_existing path does (matching main overlay pattern).
- shortcut reminder should use
CanJoinAllSpaces(visible on all Spaces simultaneously). chat and main overlay should useMoveToActiveSpace(moved to current Space on show, then flag removed to pin).
log locations
macOS: ~/.screenpipe/screenpipe-app.YYYY-MM-DD.log
Windows: %USERPROFILE%\.screenpipe\screenpipe-app.YYYY-MM-DD.log
Linux: ~/.screenpipe/screenpipe-app.YYYY-MM-DD.log
what to grep for
# crashes/errors
grep -E "panic|SIGABRT|ERROR|error" ~/.screenpipe/screenpipe-app.*.log
# monitor events
grep -E "Monitor.*disconnect|Monitor.*reconnect|Starting vision" ~/.screenpipe/screenpipe-app.*.log
# frame skip rate (debug level only)
grep "Hash match" ~/.screenpipe/screenpipe-app.*.log
# queue health
grep "Queue stats" ~/.screenpipe/screenpipe-app.*.log
# DB contention
grep "Slow DB" ~/.screenpipe/screenpipe-app.*.log
# audio issues
grep -E "audio.*timeout|audio.*error|device.*disconnect" ~/.screenpipe/screenpipe-app.*.log
# window/overlay issues
grep -E "show_existing|panel.*level|Accessory|activation_policy" ~/.screenpipe/screenpipe-app.*.log
12. mainland china / great firewall
- full app functionality behind GFW — download, onboarding, AI chat, cloud features, and update checks must all work (or degrade gracefully) on networks subject to the Great Firewall.
- HF_ENDPOINT Chinese mirror — verify model downloads work in China via the HF mirror. (
7ea1eb94e)
22. WhatsApp Gateway
commits: cf2dcd5f8, ad1d00d8f, 6f623b30a, aaf031169
- WhatsApp gateway auto-restart — Manually terminate the WhatsApp gateway process. Verify the watchdog restarts it automatically. (
cf2dcd5f8) - WhatsApp gateway self-termination — Kill the main screenpipe process. Verify the WhatsApp gateway process also terminates. (
ad1d00d8f) - WhatsApp history & contacts sync — Verify that WhatsApp chat history and contacts are correctly synchronized. (
aaf031169) - WhatsApp auto-reconnect — Verify the WhatsApp gateway automatically reconnects on server start. (
6f623b30a)
23. Notifications
- Restart notifications toggle — Toggle "restart notifications" in settings. Verify notifications only appear when enabled. (
f82b4f350) - Notification text selection — Verify that text can be selected in notification inbox messages. (
3449197c3) - macOS notification "Open" click — Click "Open" on a macOS system notification. Verify it correctly brings the Screenpipe window to the front. (
3e86cebb0)
26. Onboarding & Fleet UX
commits: f6c21a022, 31e67ae1c, 8d0a5348d, b1c30e99b
- Redesigned Onboarding — Complete the redesigned onboarding. Verify live feed appears and opinionated pipe setup works. (
f6c21a022) - Pipes & Fleet merged UI — Open Pipes tab. Verify fleet devices appear in the dropdown. Verify local machine is filtered/distinct. (
31e67ae1c,8d0a5348d) - Scheduled vs Manual pipes — In My Pipes, verify sub-tabs for scheduled and manual pipes. (
b1c30e99b)
27. Connections (Multi-instance & New Services)
- Microsoft 365 / Teams — Verify that Microsoft Graph OAuth works for Microsoft 365 and Teams (excluding personal accounts). (
635c32347,f35e999b0) - New Integrations — Verify Loops, Resend, and Supabase integrations. (
ea454f324) - Google Docs Read/Write — Verify Google Docs integration supports both read and write scopes. (
8f3ca5283)
commits: c8769545b, 4f522325b, 54000c295
- Multi-instance connections — Add two different accounts for the same service (e.g., two Slack workspaces). Verify both work independently. (
c8769545b) - Post-install connection modal — After installing a pipe, verify the connection modal appears if the pipe requires a service connection. (
c8769545b) - New service connections — Verify Brex, Stripe, Sentry, Vercel, Pipedrive, Intercom, and Limitless connections can be authorized and sync data. (
4f522325b,54000c295) - Multi-instance OAuth for GitHub and Notion — Verify that multi-instance OAuth works for GitHub and Notion, including fetching identity after token exchange. (
5d6ee5da3) - Glean icon in connections grid — Verify that the Glean icon is displayed in the connections grid. (
ec6374e1d) - Google Docs connection & Pro gate — Verify that Google Docs connection works and that the "Pro required" gate correctly appears for non-pro users on the connect button. (
9835b09d8,dbf451f34,dda16447c,e3a2be5cb) - Bitrix24 CRM integration — Verify that Bitrix24 CRM connection can be authorized and syncs data correctly. (
55026df56) - OAuth auto-refresh — Verify that expired OAuth tokens for generic proxy connections (like Google, Bitrix24) are automatically refreshed. (
d7835eabb)
28. Deployment & Remote Management
commits: c6a73b17e, 945b687ec
- Deploy to offline devices — Use chat prompt to deploy screenpipe to an offline device. Verify it handles the "Screen Sharing" permission dialog by opening it on the target machine. (
c6a73b17e,945b687ec)
29. Browser Extension
-
Extension popup — Open the browser extension popup. Verify connection status is displayed correctly. (
be7c9e8b5) -
Browser extension token auth — Open the browser extension options page. Verify that token-based authentication works and that it can successfully connect to the Screenpipe API. (
be14de544)
30. CLI
- CLI logout — Run
screenpipe logout. Verify it clears local auth tokens. (793c3d6e9) - CLI sync remote — Verify
screenpipe sync remotecommand and its configuration. (f46e85cb1)
31. Chat (Pi)
- Parallel chats — Verify that multiple chat sessions can run in parallel and their background streams remain visible when switching. (
c9d64ce23) - Chat sidebar navigation — Verify that the chat sidebar (pinned, recents, live status) works correctly and replaces the Home view for "New chat". (
ec5e80992,28c4b1ac5) - Persistent background chats — Verify that chats continue to stream in the background even when navigating away from the chat view. (
0060ae9e5,ec5e80992) - Inline history in overlay — Verify that inline history is restored in the overlay window. (
15b419ec7) - Notification URL actions — Open a URL action from a native macOS notification when the overlay is not mounted. (
7fdcd2054)
32. Updates (tray "Restart to update")
commits: 2026-08-11 tray-update-ux
- Tray restart while signed out — On a signed-out / entitlement-gated install (engine never starts, boot phase
idle), stage an update and click the tray "Restart to update". It MUST proceed and relaunch — before this fix the click silently no-oped forever (MacBook Air report). - Tray click feedback — Clicking "Restart to update" immediately changes the menu item to "Installing update…"; a deferred/failed restart shows a native notification instead of doing nothing.
- TCC-safe install — Start with healthy capture, apply an update, and verify the replacement records a new frame without toggling Screen Recording or reopening the app. The updater must not create
staged-update/replaced/previous.app. - Failed-install detection — If an update quits but doesn't apply, the next boot shows "Update didn't apply — click to retry" (marker in
~/.screenpipe/update-attempt.json, consumed once). - No-update click safety — Clicking the menu item with nothing staged runs a check and must NOT restart the app.
Automated: bun run test:e2e:packaged-updater:macos drives all of the above against two real signed release-local builds (macOS only). Rust unit coverage: cargo test --features e2e staged_update:: updates::tests (verified deferred install, no previous.app, idle gate, marker classification).